Search the Community
Showing results for tags 'save'.
-
In this tutorial we will add features to real-time tactic/strategy game in Ultra Engine fro prev tutorial: Plan: 1. Add flag model to use when pointing where to go for units 2. Make save/load system with quick save 3. Make blood particle emitter which will be used on hits and use it in Unit::Methood 4. Make blood decals which will be on the ground after death and spawn it in Unit::Kill 5. Download and use sounds for units getting damage. In this tutorial used 2117 Build from Steam Beta branch (Dev in Standalone version). In 0.9.8 version Component::Load/Save are protected. Build number can be found in the Editor Help->About Flag Flag will represent a place that player units will try to reach. Model can be found here: https://sketchfab.com/3d-models/triangle-flag-adadd59fd56d44f7b0354d1caba38f95 Download .glb version and put it to new folder "triangle_flag" in Models. Convert to mdl in the Editor. By default this model is too small. Set Scale 5.0 in Transform tab and in Tools click Reset Transform (works properly atm only for non-animated models) to save new size for good. Also click on Collapse in Tools to unite all meshes so it would be shown like single entity in a scene (otherwise this entity will have some kids which is not critical, but it's better to make it simpler). triangle_flag.zip Flag prefab: 1. Put triangle_flag model to scene 2. In Physics Collision type - None and Pick Mode - None 3. Attach WayPoint component 4. In Appearance tab in add "Save" to tags - it will be needed eventually for game save/load system 5. Save as prefab called FlagWayPoint in Prefabs folder FlagWayPoint.zip Updating classes Let's update Unit class for using getting an entity as target point and save system later. Add new method to Unit.h: void goTo(shared_ptr<Entity> targetPointEntity, bool isForced = false); In Unit.cpp method implementation: void Unit::goTo(shared_ptr<Entity> targetPointEntity, bool isForced) { if (targetPointEntity) { isForcedMovement = isForced; targetPoint = targetPointEntity; goTo(); } } Add to Start() a new tag: entity->AddTag("Save"); And also in Start() after that: if (seq != -1) { //to disable pain state at end of pain animation model->skeleton->AddHook(seq, count - 1, EndPainHook, Self()); } Add this: if (health <= 0) { seq = model->FindAnimation(deathName); int count = model->CountAnimationFrames(seq); model->Animate(deathName, 1.0f, 250, ANIMATION_ONCE, count - 1); } It's needed to make Unit make lie down in death animation if it was killed when game was save. Add a little bit below after healthBar initialization nex tline: healthBar->SetScale((float)health / (float)maxHealth, 1, 1); So health bar would have correct size after a game loading. We also want to save selected state after a loading so add first line to Load and second to Save: if (properties["isSelected"].is_boolean()) isSelected = properties["isSelected"]; properties["isSelected"] = isSelected; After line this line in Kill method: ListenEvent(EVENT_TIMERTICK, removeEntityTimer, RemoveEntityCallback, Self()); Add this: //not saving if supposed to be deleted anyway entity->RemoveTag("Save"); Current Unit: Unit.zip First version of TopDownCamera had an issue that would appear after game load: Update init() method to make it update pivot after game load: if (gameCamera && !targetPivot.lock()) { gameCamera->Listen();//for positional sound gameCamera->SetSweptCollision(true);//for removing pop up effect after quick move/turn gameCamera->SetRotation(CAMERA_PITCH, gameCamera->GetRotation(true).y, gameCamera->GetRotation(true).z); auto targetPivotShared = CreatePivot(gameCamera->GetWorld()); targetPivotShared->SetPickMode(PICK_NONE); sceneWeak.lock()->AddEntity(targetPivotShared); targetPivot = targetPivotShared; } //setting position and rotation here in case of game load gameCamera->SetParent(nullptr); auto targetPivotShared = targetPivot.lock(); auto targetPosition = getCirleCenter(gameCamera->GetPosition(true), gameCamera->GetRotation(true)); targetPosition.y = 0; targetPivotShared->SetPosition(targetPosition); targetPivotShared->SetRotation(0, gameCamera->GetRotation(true).y, gameCamera->GetRotation(true).z); gameCamera->SetParent(targetPivotShared); return true; TopDownCamera.zip In StrategyController.cpp update Start to add tag for Save next to another tag line entity->AddTag("Save"); To Save method add saving selected units: properties["selectedUnits"] = {}; int index = 0; for (auto const& selectedUnitWeak : selectedUnits) { auto selectedUnit = selectedUnitWeak.lock(); if (selectedUnit) { properties["selectedUnits"][index] = selectedUnit->GetUuid(); index++; } } Add their loading to Load: selectedUnits.clear(); if (properties["selectedUnits"].is_array()) { for (int i = 0; i < properties["selectedUnits"].size(); i++) { auto unit = scene->GetEntity(properties["selectedUnits"][i]); if (unit) { selectedUnits.push_back(unit); } } } Find this line for (auto const& entityWeak : selectedUnits) { Replace a code from starting from line above this line and ended 8 lines lower with this snippet: } else if (!selectedUnits.empty()) { auto flag = LoadPrefab(camera->GetWorld(), "Prefabs/FlagWayPoint.pfb"); if (flag) { flag->SetPosition(pick.position); } for (auto const& entityWeak : selectedUnits) { auto entityUnit = entityWeak.lock(); if (entityUnit && entityUnit->GetComponent<Unit>()) { if (flag) { entityUnit->GetComponent<Unit>()->goTo(flag, true); } else { entityUnit->GetComponent<Unit>()->goTo(pick.position, true); } } } } Or just download full class: StrategyController.zip Custom Save/Load system Current official system have a lot of flaws which are listed here: Most of them will be fixed, but something like no loading entities, which were added while run time like flags in this game, may still persist. This one is resolved by loading prefabs. You can also add manual recreation for most types of entities, depends on needs, but prefabs should be enough in most cases. Game class have a lot of changes, which were made to create custom save system. Whole Game.h: #pragma once #include "UltraEngine.h" #include "Components/Player/FPSPlayer.h" using namespace UltraEngine; class Game : public Object { protected: shared_ptr<Camera> uiCamera; shared_ptr<Scene> scene; shared_ptr<FPSPlayer> fpsPlayer; shared_ptr<Widget> menuPanel; shared_ptr<Widget> gameSavedLabel; //hide gameSavedLabel on timer shared_ptr<Timer> gameSavedLabelTimer; Game(); void init(shared_ptr<Framebuffer> framebuffer, WString mapPath); //update basic entity properties - position, rotation, tags void loadEntity(shared_ptr<Entity> entity, table entityTable); void loadGame(table saveTable); void saveGame(WString saveName); static bool QuickSaveGameCallback(const UltraEngine::Event& ev, shared_ptr<UltraEngine::Object> extra); static bool HideGameSavedLabelCallback(const UltraEngine::Event& ev, shared_ptr<UltraEngine::Object> extra); public: //to show/hide game menu on Esc static bool GameMenuButtonCallback(const Event& ev, shared_ptr<Object> extra); static std::shared_ptr<Game> create(shared_ptr<Framebuffer> framebuffer, WString mapPath); //for game loading static std::shared_ptr<Game> create(shared_ptr<Framebuffer> framebuffer, table saveTable); shared_ptr<Interface> ui; shared_ptr<World> world; }; Game.cpp: #include "UltraEngine.h" #include "Game.h" #include "CustomEvents.h" Game::Game() = default; std::shared_ptr<Game> Game::create(shared_ptr<Framebuffer> framebuffer, WString mapPath) { struct Struct : public Game {}; auto instance = std::make_shared<Struct>(); instance->init(framebuffer, mapPath); return instance; } std::shared_ptr<Game> Game::create(shared_ptr<Framebuffer> framebuffer, table saveTable) { struct Struct : public Game {}; auto instance = std::make_shared<Struct>(); std::string mapName = saveTable["MapPath"]; instance->init(framebuffer, WString(mapName)); instance->loadGame(saveTable); return instance; } bool Game::GameMenuButtonCallback(const Event& ev, shared_ptr<Object> extra) { if (KEY_ESCAPE == ev.data && extra) { auto game = extra->As<Game>(); bool isHidden = game->menuPanel->GetHidden(); game->menuPanel->SetHidden(!isHidden); if (game->fpsPlayer) { //we can get a game window anywhere, but take in mind that it will return nullptr, if window is not active ;) auto window = ActiveWindow(); //checking just in case if we actually got a window if (window) { //hiding cursor when hiding a menu and vice versa window->SetCursor(isHidden ? CURSOR_DEFAULT : CURSOR_NONE); } game->fpsPlayer->doResetMousePosition = !isHidden; } //If the callback function returns false no more callbacks will be executed and no event will be added to the event queue. //to avoid double call return false; } return true; } static bool MainMenuButtonCallback(const Event& ev, shared_ptr<Object> extra) { EmitEvent(EVENT_MAIN_MENU); return true; } static bool ExitButtonCallback(const Event& ev, shared_ptr<Object> extra) { exit(0); return true; } void Game::init(shared_ptr<Framebuffer> framebuffer, WString mapPath) { world = CreateWorld(); scene = LoadMap(world, mapPath); for (auto const& entity : scene->entities) { auto foundPlayer = entity->GetComponent<FPSPlayer>(); if (foundPlayer) { fpsPlayer = foundPlayer; break; } } auto font = LoadFont("Fonts/arial.ttf"); //Create user interface for game menu auto frameSize = framebuffer->GetSize(); ui = CreateInterface(world, font, frameSize); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition(float(frameSize.x) * 0.5f, float(frameSize.y) * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); //widgets are stays without extra shared pointers because parent widet, ui->root in this case, keep them //to remove widget you should do widget->SetParent(nullptr) menuPanel = CreatePanel(frameSize.width / 2 - 150, frameSize.height / 2 - 300 / 2, 300, 250, ui->root); gameSavedLabel = CreateLabel("GAME SAVED", frameSize.width / 2 - 100, 50, 200, 30, ui->root); gameSavedLabel->SetFontScale(2.0f); gameSavedLabel->SetHidden(true); auto menuButton = CreateButton("Main menu", 50, 50, 200, 50, menuPanel); ListenEvent(EVENT_WIDGETACTION, menuButton, MainMenuButtonCallback); auto exitButton = CreateButton("Exit", 50, 150, 200, 50, menuPanel); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback, nullptr); //we don't need game menu on screen while playing menuPanel->SetHidden(true); //and we will need it once hitting Esc button ListenEvent(EVENT_KEYUP, nullptr, GameMenuButtonCallback, Self()); //take in mind that extra param will be kept as shared_ptr in callback ^ ListenEvent(EVENT_KEYUP, nullptr, QuickSaveGameCallback, Self()); } void Game::loadEntity(shared_ptr<Entity> entity, table entityTable) { if (entityTable["position"].is_array() && entityTable["position"].size() == 3) { entity->SetPosition(entityTable["position"][0], entityTable["position"][1], entityTable["position"][2], true); } if (entityTable["rotation"].is_array() && entityTable["rotation"].size() == 3) { entity->SetRotation(entityTable["rotation"][0], entityTable["rotation"][1], entityTable["rotation"][2], true); } if (entityTable["tags"].is_array()) { for (int i = 0; i < entityTable["tags"].size(); i++) { entity->AddTag(std::string(entityTable["tags"][i])); } } } void Game::loadGame(table saveTable) { //old-new entity id vector<std::pair<String, String>> uuids; std::set<String> newEntities; //entites that was not in scene will be deleted once Components will be loaded and gets needed entities std::set<shared_ptr<Entity>> entitiesToRemoveFromScene; //iterating std::map by key (uuid) and value (entityTable) instead of pair for (auto& [uuid, entityTable] : saveTable["SavedEntities"]) { auto entity = scene->GetEntity(uuid); //load properties for saved entity that was initially on map if (entity) { loadEntity(entity, entityTable); //or if it was not we can recreate prefab at least } else if (entityTable["prefabPath"].is_string()) { //spawn saved entity that was not initially on map auto spawnedEntity = LoadPrefab(world, String(entityTable["prefabPath"])); if (!spawnedEntity) { continue; } scene->AddEntity(spawnedEntity); if (entityTable["isInScene"].is_boolean() && !entityTable["isInScene"]) { entitiesToRemoveFromScene.insert(spawnedEntity); } loadEntity(spawnedEntity, entityTable); uuids.push_back(std::pair(uuid, spawnedEntity->GetUuid())); newEntities.insert(spawnedEntity->GetUuid()); } } //delete not saved entities for (auto const& entity : world->GetTaggedEntities("Save")) { //does newEntities containes curent entity if (newEntities.find(entity->GetUuid()) != newEntities.end()) { //skip new entity continue; } //if supposed to be saved and was not due being removed when save was made then remove it from scene table entityTable = saveTable["SavedEntities"][entity->GetUuid()]; if (entityTable.empty()) { scene->RemoveEntity(entity); } } //saving table++ as a string auto saveString = String(saveTable.to_json()); //replace entities ids so component would use new ones for (auto const& [oldUuid, newUuid] : uuids) { saveString = saveString.Replace(oldUuid, newUuid); } //converting back to table++ from string saveTable = ParseJson(saveString); //Load saved data to components for (auto const& entity : world->GetTaggedEntities("Save")) { auto& entityTable = saveTable["SavedEntities"][entity->GetUuid()]; for (auto const& component : entity->components) { component->Load(entityTable, nullptr, scene, LOAD_DEFAULT, nullptr); } } //starting components now when all data is there for (auto const& entity : world->GetTaggedEntities("Save")) { for (auto const& component : entity->components) { component->Start(); } } //removing from scene entites that scene had not for (auto const& entity : entitiesToRemoveFromScene) { scene->RemoveEntity(entity); } } void Game::saveGame(WString saveName) { table saveTable; //saving map path to use it later to load correct map saveTable["MapPath"] = RelativePath(scene->path).ToUtf8String(); saveTable["SavedEntities"] = {}; for (auto const& entity : world->GetTaggedEntities("Save")) { table entityTable; for (auto const& component : entity->components) { component->Save(entityTable, nullptr, scene, SAVE_DEFAULT, nullptr); } //just to make save file more readable if (!entity->name.empty()) { entityTable["name"] = entity->name.ToUtf8String(); } //saving position and rotation of entity to restore them in Load auto position = entity->GetPosition(true); entityTable["position"] = {}; entityTable["position"][0] = position.x; entityTable["position"][1] = position.y; entityTable["position"][2] = position.z; auto rotation = entity->GetRotation(true); entityTable["rotation"] = {}; entityTable["rotation"][0] = rotation.x; entityTable["rotation"][1] = rotation.y; entityTable["rotation"][2] = rotation.z; entityTable["tags"] = {}; //to remove it from scene later once everything restored inc case if only components supposed to keep this entity entityTable["isInScene"] = scene->GetEntity(entity->GetUuid()) ? true : false; int tagIndex = 0; for (auto& tag : entity->tags) { entityTable["tags"][tagIndex] = tag.ToUtf8String(); tagIndex++; } //save prefab path to be able restore entity if it was added to scene later as prefab auto prefab = entity->GetPrefab(); if (prefab) { entityTable["prefabPath"] = RelativePath(prefab->GetPath()).ToUtf8String(); } //using entity id as key for its properties saveTable["SavedEntities"][entity->GetUuid()] = entityTable; } SaveTable(saveTable, saveName); //showing "Game Saved" labl for 2 seconds gameSavedLabel->SetHidden(false); gameSavedLabelTimer = UltraEngine::CreateTimer(2000); ListenEvent(EVENT_TIMERTICK, gameSavedLabelTimer, HideGameSavedLabelCallback, Self()); } bool Game::QuickSaveGameCallback(const UltraEngine::Event& ev, shared_ptr<UltraEngine::Object> extra) { if (KEY_F5 == ev.data && extra) { auto game = extra->As<Game>(); game->saveGame("QuickSave.save"); } return true; } bool Game::HideGameSavedLabelCallback(const UltraEngine::Event& ev, shared_ptr<UltraEngine::Object> extra) { if (extra && extra->As<Game>()) { auto game = extra->As<Game>(); game->gameSavedLabel->SetHidden(true); game->gameSavedLabelTimer->Stop(); game->gameSavedLabelTimer = nullptr; } return false; } Game.zip Add new functions to main.cpp: void LoadGame(WString savePath) { table saveTable = LoadTable(savePath); if (saveTable == nullptr) { return; } menu.reset(); //to avoid random error in World::Update() game.reset(); loadingWorld->Render(framebuffer); if (currentWorld) currentWorld.reset(); if (currentUi) currentUi.reset(); game = Game::create(framebuffer, saveTable); currentWorld = game->world; currentUi = game->ui; } bool QuickLoadGameCallback(const Event& event, shared_ptr<Object> extra) { if (KEY_F9 == event.data) { LoadGame("QuickSave.save"); } return true; } And add ListenEvent next to other similar lines: ListenEvent(EVENT_KEYUP, nullptr, QuickLoadGameCallback); main.zip Now you can save and load game with F5 and F9 respectively Making Particle Effect Download this blood texture made by TobiasM: https://opengameart.org/content/blood-splat It's not optimal for particle emitter, but good enough for learning purpose. Put into Materials\Particles folder and convert to .dds in the Editor. Generate a material from dds texture. Add to any scene particle emitter: In Appearance tab of Particles choose a recently made material. Now we able to see result when we will change this material properties. Open material: 1. Choose Lambertian shader family - it has better perfomance than PBR and it can make a difference eventually with many particle emitters which produce dozens particles. 2. In Blend tab check Transparent checkbox. Now it particles would look like that: Open Particles tab of Particle Emitter in entity properties: 1. Particle count - how many particles of this emitter exist at same time, left it as 50 2. Emission shape - shape of area where particles will be spawn 3. Emission Area - size of this area (width, height, depth). If 0 then particles spawns at same point. Left it as 0. 4. Burst frequency - how often particles spawns. Will be 800 5. Burst count - how much particles spawns in every burst. Enter 50 6. Colors - how particle looks at spawn and despawn 7. Velocity - direction and speed - make it 0 8. Acceleration - same but it's accel 9. Size - width and height of particle. No depth, because every particle is just a billboard sprite. Makie it 0.2/0.2 10. Radius. First value - relative size (i.e. 1.0 is 100%) for particle at start and second value is size when particles despawns. Value - 1.0/1.0 11. Turbulence - random speed in random direction. With 0 velocity it will make particles move in different directions. Make it 300.0 12. Rotation speed - how fast particle rotate. Make it 0 Download ParticleEffect to ParticleEffect component to Components\Appearance folder. Include into project and add to ComponentSystem as usual. Add this component to an emitter. It's needed to make blood hit effect to dissapear before it would burst again. Temporary checkbox on and Duration 700. Name emitter as BloodHit and save it as prefab "BloodHit.phb" in Prefabs folder Let's use it for units. In Unit.cpp in Damage method add next code somewhere above auto now = world->GetTime(); auto bloodHit = LoadPrefab(world, "Prefabs/BloodHit.pfb"); auto entity = GetEntity(); if (bloodHit) { auto bloodHitPosition = entity->GetPosition(true); //to lift it up to entity center bloodHitPosition.y = bloodHitPosition.y + entity->GetBounds(BOUNDS_GLOBAL).size.height / 2; bloodHit->SetPosition(bloodHitPosition, true); //prefabs component are not started after its load so will do it manually for (auto const& component : bloodHit->components) { component->Start(); } } Making decal Copy blood_splat.dds texture to Materials\Decals folder. Generate a new material from it and name BloodPuddle. Edit this material: 1. Keep PBR as shader family. 2. In Blend tab check Transparent checkbox. 3. In Surface Metalness 0, and Roughness 50. Add new decal to scene - 256x256 size with 16 height (or 250x250 and 20) Choose new material in appearance. Save this decal as prefab wiht BloodPuddle name. We will spawn this decal after unit death. In Unit::Kill() method add above auto model = entity->As<Model>(); line following code: auto scene = sceneWeak.lock(); auto bloodPuddle = LoadPrefab(entity->GetWorld(), "Prefabs/BloodPuddle.pfb"); if (bloodPuddle && scene) { auto bloodHitPosition = entity->GetPosition(true); bloodPuddle->SetPosition(bloodHitPosition, true); //to keep it scene->AddEntity(bloodPuddle); } Pain sounds Download sounds for Warrok: https://opengameart.org/node/132772 And for Paladin: https://opengameart.org/content/pain-sounds-by-emopreben In Sounds folder create Units subfolder and put there bear_02.ogg from 1st pack and "Painsounds v2 - Track 5 - Urggh.ogg" from 2nd Add to properties in Unit.json: { "label": "Pain sound", "name": "painSound", "value": "", "filecategory": "SOUND" }, New member in Unit.h header: shared_ptr<Sound> painSound; In Load method in Unit.cpp will load attached in the Editor sound: if (properties["painSound"].is_string()) painSound = LoadSound(std::string(properties["painSound"])); And play this sound in Damage() above auto now = world->GetTime(); line: if (painSound) { entity->EmitSound(painSound); } Unit class: FinalUnit.zip Now open Paladin prefab and add their pain sound in Unit component. Same for Warror. Delete units from Strategy map and add them again from prefabs. Remember to break prefab after that. strategy.zip Cache In debug mode you could notice micro-freezes when prefabs are loaded every time when it's not at the map. Thats because unload from memory an assets that have no shared_pointer to them. We can fix by making cache in Game class. Add to Game.h new member: vector<shared_ptr<Entity>> prefabCache; And at the end of init method in Game.cpp: //caching prefabCache.push_back(LoadPrefab(world, "Prefabs/BloodPuddle.pfb")); prefabCache.push_back(LoadPrefab(world, "Prefabs/BloodHit.pfb")); prefabCache.push_back(LoadPrefab(world, "Prefabs/FlagWayPoint.pfb")); for (auto const& prefab : prefabCache) { if (prefab) { prefab->SetHidden(true); } } GameCache.zip Now Debug mode will be smoother since assets loaded on game load and not in run time when components uses them. In Release mode it would be also necessary to do for heavy assets. Final version on github: https://github.com/Dreikblack/CppTutorialProject/tree/4-save-load-particles-decals
-
Current Save/Load system have flows & bugs and public Component::Save/Load would allow to make custom universal one. In Lua they should be usable as well, with allowable nil for binstream & extra or as overload with just table, scene with optionable extra. Also it would allow to use those methods for other purposes, including save and sending only single component via network etc. Current issues are: All entities are saved - when in fact only 20% or less might be actual needs saving. Beside extra entities it's also saves flowgraph and other binary data And such extra data making "save" file is too big, because it's actually a map which is already too much for save files and can't be used for sure for network stuff. Reload() breaks lights and does not remove entities that were removed from scene before saving. No ability to add own properties, which save file may need It would be nice to have working save/load system in Ultra, but at this moment it's necessary to have at least Load/Save available to user both C++ and Lua so i could finish custom save/load system without users having to wait another months/years before official one will be ready for actual use. While working on my game such system saved me a ton of times and would help a lot other people, but i can't make it universal atm.
-
Hello, I'll get straight to the point, looking to create UI that incorporates Save/Load functionality. I did see Piller's download for save load and saying it should be attached to Pivot, however wish to further extend that whole thing by creating custom UI with Save Load and options... Any advice on how to accomplish this? Thank you,
-
Hello, Because I made myself some thoughts about a saving mechanic for my current project, I searched the web and especially the Leadwerks site for how to save simple game data, like the players health or position. The only kind of useful thing I found which works for LUA was this: http://www.leadwerks.com/werkspace/topic/2103-save-data-to-lua-syntax-as-textcompressed/page__hl__save+data and this: http://www.leadwerks.com/werkspace/topic/1853-howto-using-lua-script-as-data-file/ I actually was able to create a data file and read it into my code with "dofile". However I didnt find out how to create/save a file with lua yet. I searched the Leadwerks API and found the Stream and FileSystem Class. So I tried the following code: function Script:Start() local gamedata = FileSystem:WriteFile("Test.txt") end It didnt work, and I also dont know how it works. Where has the file been created? I searched my PC and the Projectsfolder but couldnt find such a file and I also dont get any kind of error message. I guess this is completely wrong, but I was just playing around, because I don't have that much experience with Lua and Leadwerks. The file you can download in the first thread I posted ("TStoreData.lua") doesnt work anymore and I cant find where he saves data. That you clearly undersand what I want. I would like to do something like this: function Script:Start() local gamedata = {} gamedata.playerHealth = 100 gamedata.playerWeapon = "Sword" gamedata.playerPos = Vec3(10, 100, 53) FileSystem:WriteFile("gamedata.lua", gamedata) end This is just some code that you know what I mean. I know this doesnt work xD. So could you please help me out a little bit . PS.: I kind of understood what AndyGFX wrote in his post, I just couldnt find anything how to save a file.
-
I wish for Leadwerks some functions for saving 3D model stuff. Not inside the editor, I wish to export a model in .fbx format and .mdl as a prefab it would also be nice.
-
just ideas/thoughts at auto save option its not clear if it wrote only a backup file or just save the map. at run the map is saved. the * from filename disappear, so i think the maps is overwritten. what if i do some tests in my map? i lost the original file? in my view the autosave save .autosave.map at run save as .beforerun.map or .temp.map at save .map > .backup1...5.map then save .map
-
This is a bug that happens a lot to me. After placing objects and working on terrain my map won't save and then all my work will be deleted. I believe this is caused by the same bug that was pointed out in my last post - http://www.leadwerks.com/werkspace/topic/10631-directional-light-and-model-editor-bug/ I really can't do any more work like this. I have lost to many hours of my time to this specific issue. Looks like the Hunt for Food is on hold. Video - https://www.youtube.com/watch?v=mjyjNBnFnTM&feature=youtu.be I can provide my project if needed, just let me know. Edit-- I looked into my backup maps and all the backups are named temp.map and when I try to open them I get Exception Access Violation.