Здесь расскажу как сделать в 3D Rad так, чтобы можно было сохранить состояние персонажа в одном из трех слотов, и даже при перезапуске проекта загрузить любой из них. Итак мы создаем Terrain, Skybox,G-Force и Cam1StPerson. Далее жмем Object>Add и двойной щелчок на Script. Не подумайте, что мне лень всё подробно объяснять, но дабы не морочить вам голову, я решил написать скрипт здесь, ну а ваши золотые руки его скопируют и вставят к себе. Vector3 Player,Collect1,Collect2,Collect3,Enemy1,Enemy2; string Quicksave1=".\\quicksave1.txt"; string Quicksave2=".\\quicksave2.txt"; string Quicksave3=".\\quicksave3.txt"; int FileHandle,Wait,Counter,Health,Collected1,Collected2,Collected3; void Main() { //Stage 1 - Set all variables to desired initial value and read fish locations //into vectors. if(iInitializing()) { Wait=0; Counter=0; Collected1=0; Collected2=0; Collected3=0; iObjectLocation(OBJ_220,Player); iObjectLocation(OBJ_0,Collect1); iObjectLocation(OBJ_22,Collect2); iObjectLocation(OBJ_44,Collect3); } iObjectLocation(OBJ_220,Player); //Stage 2 - Handle visibility of collectable fish. If a file is loaded in which all //fish have already been collected, none will be visible. if(Collected1==0){ iObjectShow(OBJ_0); } else{ iObjectHide(OBJ_0); } if(Collected2==0){ iObjectShow(OBJ_22); } else{ iObjectHide(OBJ_22); } if(Collected3==0){ iObjectShow(OBJ_44); } else{ iObjectHide(OBJ_44); } //Stage 3 - Based on the same 'collected' variables as used above, determine whether the //player can acquire a fish. if(iVectorLength(Player-Collect1)<1 && Collected1==0) { iObjectHide(OBJ_0); iObjectStart(OBJ_66); Collected1=1; } if(iVectorLength(Player-Collect2)<1 && Collected2==0) { iObjectHide(OBJ_22); iObjectStart(OBJ_66); Collected2=1; } if(iVectorLength(Player-Collect3)<1 && Collected3==0) { iObjectHide(OBJ_44); iObjectStart(OBJ_66); Collected3=1; } //Stage 4 - Counter used for hiding saving/loading text after it is visible for 1 second. if(Wait==2) { Counter++; } if(Counter==60) { Counter=0; Wait=0; iObjectHide(OBJ_176); } //Stage 5 - Define quicksaving with keys F1,F2,F3. Use the 'wait' variable to ensure the system //completes a save before another can be made. if(iKeyDown(iKeyCode("DIK_F1")) && Wait==0) { Wait=1; FileHandle=iFileWriteOpen(Quicksave1); if(FileHandle!=-1) { iFileValueWrite(FileHandle,Player.x,true); iFileValueWrite(FileHandle,Player.y+2,true); iFileValueWrite(FileHandle,Player.z,true); iFileValueWrite(FileHandle,Health,true); iFileValueWrite(FileHandle,Collected1,true); iFileValueWrite(FileHandle,Collected2,true); iFileValueWrite(FileHandle,Collected3,true); iFileClose(FileHandle); iObjectTextSet(OBJ_176,"Quicksaving in slot 1..."); iObjectShow(OBJ_176); Wait=2; } } if(iKeyDown(iKeyCode("DIK_F2")) && Wait==0) { Wait=1; FileHandle=iFileWriteOpen(Quicksave2); if(FileHandle!=-1) { iFileValueWrite(FileHandle,Player.x,true); iFileValueWrite(FileHandle,Player.y+2,true); iFileValueWrite(FileHandle,Player.z,true); iFileValueWrite(FileHandle,Health,true); iFileValueWrite(FileHandle,Collected1,true); iFileValueWrite(FileHandle,Collected2,true); iFileValueWrite(FileHandle,Collected3,true); iFileClose(FileHandle); iObjectTextSet(OBJ_176,"Quicksaving in slot 2..."); iObjectShow(OBJ_176); Wait=2; } } if(iKeyDown(iKeyCode("DIK_F3")) && Wait==0) { Wait=1; FileHandle=iFileWriteOpen(Quicksave3); if(FileHandle!=-1) { iFileValueWrite(FileHandle,Player.x,true); iFileValueWrite(FileHandle,Player.y+2,true); iFileValueWrite(FileHandle,Player.z,true); iFileValueWrite(FileHandle,Health,true); iFileValueWrite(FileHandle,Collected1,true); iFileValueWrite(FileHandle,Collected2,true); iFileValueWrite(FileHandle,Collected3,true); iFileClose(FileHandle); iObjectTextSet(OBJ_176,"Quicksaving in slot 3..."); iObjectShow(OBJ_176); Wait=2; } } //Stage 6 - Define quickloading with keys F4,F5,F6. Observe the order in which the variables //are written/read to/from the txt file. if(iKeyDown(iKeyCode("DIK_F4")) && Wait==0) { Wait=1; FileHandle=iFileReadOpen(Quicksave1); if(FileHandle!=-1) { Player.x=iFileValueRead(FileHandle); Player.y=iFileValueRead(FileHandle); Player.z=iFileValueRead(FileHandle); OUT_154=iFileValueRead(FileHandle); Collected1=iFileValueRead(FileHandle); Collected2=iFileValueRead(FileHandle); Collected3=iFileValueRead(FileHandle); iFileClose(FileHandle); iObjectTextSet(OBJ_176,"Quickloading from slot 1..."); iObjectShow(OBJ_176); iObjectHide(OBJ_220); Wait=2; iObjectLocationSet(OBJ_220,Player); iObjectShow(OBJ_220); } } if(iKeyDown(iKeyCode("DIK_F5")) && Wait==0) { Wait=1; FileHandle=iFileReadOpen(Quicksave2); if(FileHandle!=-1) { Player.x=iFileValueRead(FileHandle); Player.y=iFileValueRead(FileHandle); Player.z=iFileValueRead(FileHandle); OUT_154=iFileValueRead(FileHandle); Collected1=iFileValueRead(FileHandle); Collected2=iFileValueRead(FileHandle); Collected3=iFileValueRead(FileHandle); iFileClose(FileHandle); iObjectTextSet(OBJ_176,"Quickloading from slot 2..."); iObjectShow(OBJ_176); iObjectHide(OBJ_220); Wait=2; iObjectLocationSet(OBJ_220,Player); iObjectShow(OBJ_220); } } if(iKeyDown(iKeyCode("DIK_F6")) && Wait==0) { Wait=1; FileHandle=iFileReadOpen(Quicksave3); if(FileHandle!=-1) { Player.x=iFileValueRead(FileHandle); Player.y=iFileValueRead(FileHandle); Player.z=iFileValueRead(FileHandle); OUT_154=iFileValueRead(FileHandle); Collected1=iFileValueRead(FileHandle); Collected2=iFileValueRead(FileHandle); Collected3=iFileValueRead(FileHandle); iFileClose(FileHandle); iObjectTextSet(OBJ_176,"Quickloading from slot 3..."); iObjectShow(OBJ_176); iObjectHide(OBJ_220); Wait=2; iObjectLocationSet(OBJ_220,Player); iObjectShow(OBJ_220); } } //Stage 7 - Constantly print out health value and score=collected1+collected2+collected3 Health=IN_154; OUT_88=Collected1+Collected2+Collected3; OUT_132=Health; } ___________________________________________________ После скрипта, создаем TextPrint, и пишем в нем save/load status, и для красоты размещаем в верхнем левом углу.Так же привязываем его к скрипту. (сo скриптом должны быть связанны Cam1StPerson;TextPrint) ___________________________________________________ Итак, теперь создаем три "рыбки", Skinmesh, ну и ставим недалеко друг от друга (по желанию).(Связываем их сo скриптом) ___________________________________________________ Далее жмем опять Object>Add>Counter; В параметрах Counter делаем вот что: Initial Value [100] Increment (can be negative) [ -1 ] Wrapping/clamping range [ 0 ] [100] [Clamp] Cross-project file [ ] [Read at startup and write on exit] Привязываем Counter к скрипту. __________________________________________________ Создаем два RigidBody, ставим в разных местах и связываем с Cam1StPerson. Теперь добавляем EventOnContact, и привязываем к нему Cam1StPerson; RigidBody1;RigidBody2;Counter. Открываем настройки EventOnContact: Cam1StPerson________ MONITOR RigidBody1_____________________ MONITOR Counter____________________ START ON CONTACT RigidBody2_____________________ MONITOR __________________________________________________ Завершающий этап: Создаем TextPrint, в нем пишем Health (размещаем примерно в вверхнем правом углу) Создаем ValuePrint, ставим чуть правее от health и связываем с скриптом.(в настройках IGNORE к скрипту) То же самое со Score. Создаем TextPrint, в нем пишем Score и размещаем под Health. Создаем ValuePrint, ставим чуть првее от Score и связываем сo скриптом. (в настройках IGNORE к скрипту) Далее добавляем SoundEffect и привзываем к скрипту. Всё! Вот демка, где сделанно все вышенаписанное. |