Jump to content

Andy90

Developers
  • Posts

    219
  • Joined

  • Last visited

Everything posted by Andy90

  1. Andy90

    PBR Bug

    This could also an bug from the model it self. Another model is working fine.
  2. For some reason child entitys from mdl models dont have any tags. Even if they are assigned within the editor.
  3. Andy90

    PBR Bug

    In this model the pbr dont get loaded correct. Whit windows 3D view everything looks fine Blue.zip
  4. According to my discord post i upload here the model where the problemm happens. https://drive.google.com/file/d/1iqW0j6to9H0XicAe3CFlseViVGf46UN1/view?usp=sharing
  5. Now that we have a transformation gizmo, a function or shortcut for disabling grid snapping would be helpful. So that you can position entities more precisely
  6. It would be good if we could get more input options for components in the editor. Such as lists for entities, strings, floats, Vec3 and files. Like in the example bellow.
  7. There is a problem with the prefabs. If you create a prefab, drag it into the scene and then save the scene, it spawns in the game in the wrong location or is not visible at all. (due to the wrong positioning)
  8. It's your decision, of course, but I personally don't think it's contemporary that a scene can only have one terrain.
  9. so its not possible to create an world out of multiple terrains ?
  10. In this article, I would like to delve into the concept of "Game Logs" and explain why they play an important role. First, however, we should clarify what exactly a Game Log is. The Game Log allows us to log and temporarily store various actions in the game. Furthermore, with the help of the Game Log, we can inform independent systems about various actions. A good example of this is a simple quest system, similar to the one in World of Warcraft. In such systems, we want to complete quests by, for example, looting a specific item, killing a certain enemy, or interacting with a specific NPC. But how are the individual quests supposed to know exactly when we loot an item? Sure, one could simply search through the inventory. However, that would only work for quest types where we are supposed to loot an item, and not for those where we are supposed to kill a specific enemy or talk to an NPC. This is where the Game Log proves to be extremely useful, as our quests can simply search through the entries to update themselves accordingly. In the past few days, I have been working on implementing such a system in C++. It is important to note that this is not a component; instead, a "Global.h" file is required, where the log is defined as a global variable. GameLog.h #pragma once #include "UltraEngine.h" using namespace UltraEngine; /// <summary> /// Event types /// </summary> enum GameLogEvent { GAME_LOG_LOOT_ITEM, GAME_LOG_KILL_ENEMY }; /// <summary> /// Game Log entrys /// </summary> struct GameLogEntry { String uuid; uint64_t timestamp; GameLogEvent event; table data; }; /// <summary> /// GameLogListner forward declaration /// </summary> class GameLogListener; /// <summary> /// Handles the game log entrys /// </summary> class GameLog { private: vector<shared_ptr<GameLogListener>> m_listeners; vector<GameLogEntry> m_log; public: void Log(GameLogEvent event, table eventData); void AddListener(shared_ptr<GameLogListener> listener); void LogLootItem(String itemName, int itemCount); void LogKilledEnemy(String enemyName); void Clean(uint64_t time); vector<GameLogEntry> FetchLog(uint64_t startTime); }; GameLog.cpp #include "UltraEngine.h" #include "GameLog.h" #include "GameLogListener.h" void GameLog::Log(GameLogEvent event, table eventData) { GameLogEntry entry; entry.uuid = Uuid(); entry.timestamp = Millisecs(); entry.event = event; entry.data = eventData; m_log.push_back(entry); for (auto listener : m_listeners) { if (listener->Event == event) { listener->Callback(eventData); } } Print("Added data to gamelog"); } void GameLog::AddListener(shared_ptr<GameLogListener> listener) { m_listeners.push_back(listener); } void GameLog::LogLootItem(String itemName, int itemCount) { table data; data["itemName"] = itemName; data["itemCount"] = itemCount; Log(GAME_LOG_LOOT_ITEM, data); } void GameLog::LogKilledEnemy(String enemyName) { table data; data["enemyName"] = enemyName; Log(GAME_LOG_KILL_ENEMY, data); } void GameLog::Clean(uint64_t time) { vector<GameLogEntry> newEntrys; for (auto entry : m_log) { auto diff = Millisecs() - entry.timestamp; if (diff <= time) { newEntrys.push_back(entry); } else { Print("Entry " + entry.uuid + " out of time!"); } } m_log = newEntrys; } vector<GameLogEntry> GameLog::FetchLog(uint64_t startTime) { vector<GameLogEntry> result; for (auto entry : m_log) { if (entry.timestamp > startTime) { result.push_back(entry); } } return result; } In the file GameLog.h, we find an enum with various events, to which more can be added. Currently, there are entries for looting an item and killing an enemy. Furthermore, the structure "GameLogEntry" defines various variables, including a string for a UUID, a long variable for the timestamp, the event, and the data of the entry. Following that is the main class, which contains various functions as well as two lists. One list is for so-called hooks, and the other is for the log itself. Here's an overview of the functions: Log(): Adds entries to the log. AddListener(): Adds a callback (no callback is needed in this article). LogLootItem(): Simplifies adding a loot event to the game's log. LogKilledEnemy(): Simplifies adding a kill event. Clean(uint64_t time): Deletes all entries older than the specified parameter in milliseconds. vector<GameLogEntry> FetchLog(uint64_t startTime): Returns a list of log entries whose timestamp is greater than the start time in the parameter. If we want to determine whether we have looted an item or killed a specific enemy, we can simply retrieve the log. It is important to store the time of the last query so that we only receive the entries that are still unknown to us. void VitalUI::UpdateNotifications() { m_notifyer->ClearItems(); auto fetchTime = Millisecs() - 5000; auto log = g_log.FetchLog(fetchTime); for (auto entry : log) { if (entry.event == GAME_LOG_LOOT_ITEM) { m_notifyer->AddItem("Looted " + String(entry.data["itemName"]) + " (X" + String(entry.data["itemCount"]) + ")"); } } if (m_notifyer->items.size() > 0) { m_notifyer->Redraw(); } } To ensure that the log does not grow infinitely, it is advisable to clear it regularly. In my implementation, I clear the log every 6 minutes in the main loop. That should be sufficient to process all events. while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { const Event ev = WaitEvent(); g_ui->GetInterface()->ProcessEvent(ev); switch (ev.id) { case EVENT_WIDGETACTION: break; case EVENT_WINDOWCLOSE: return 0; break; } } world->Update(); world->Render(framebuffer, false, 0); g_log.Clean(60000); } As you can see, a Game Log has become extremely practical and indispensable in modern games. If you have any questions about this article, feel free to contact me. Additionally, it's worth mentioning that the log can be used for many other purposes and is not limited to just a quest system. Gamelog.zip
  11. I think its an issue with the model itself. Check this model Vampire.rar
  12. well i my case a simple stamp tool is enough. Because right now you cant controll the height in the sculpt mode
  13. okey i think this would be the easy way to do it. Instead of replace some mesh verticies. Thanks
  14. ah so in summory you added all cloths to the character and just hide all the cloth meshs. When a player equip some shirt you show this mesh again.
  15. With this straightforward component, you can specify the pick mode for the entity. Options include None, Mesh, and Collider. The pick mode is automatically and recursively configured for each child entity. Pickmode.zip
  16. Hey, as I'm porting my game from Leadwerks to Ultra, I've come across some important terrain tools that are currently not available in the engine. Terrain Stamping: Having a function to raise or lower the terrain at a given height would be beneficial. For example, I'm trying to create a harbor, but I'm unable to create smooth terrain around the harbor base model. Terrain Smoothing: There are times when you want to smooth out the terrain to eliminate sharp edges.
  17. i think you would need the bone weights for it.
  18. I'm considering a clothing system in Ultra and how I could implement it. Essentially, there are two approaches. One is to simply split the mesh into four parts (head, body, legs, and feet) and create different meshes with clothes for each part. The second, and in my opinion better, approach is to handle the clothes separately from the player model itself. This means having a blank model for your player and attaching the clothes to it. However, I'm not sure if this is possible. Additionally, I'm uncertain about how to do this.
  19. I think you need an gltf not glb file.
  20. The scene list for the entity picker insidee the components is empty
  21. I think it was about the lod generation. The lod generation should be not related to the terrain only.
  22. Hello, when you change a map the usage memory increase but never decrease. This means there is something allive what should not be allive. You can reproduce it with this code. Just hit multiple times T and see how the memory increases every time. #include "UltraEngine.h" #include "ComponentSystem.h" //#include "Steamworks/Steamworks.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { #ifdef STEAM_API_H if (not Steamworks::Initialize()) { RuntimeError("Steamworks failed to initialize."); return 1; } #endif RegisterComponents(); auto cl = ParseCommandLine(argc, argv); //Load FreeImage plugin (optional) auto fiplugin = LoadPlugin("Plugins/FITextureLoader"); //Get the displays auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * displays[0]->scale, 720 * displays[0]->scale, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a framebuffer auto framebuffer = CreateFramebuffer(window); //Create a world auto world = CreateWorld(); //Load the map WString mapname = "Maps/start.ultra"; if (cl["map"].is_string()) mapname = std::string(cl["map"]); auto scene = LoadMap(world, mapname); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { world->Update(); world->Render(framebuffer); #ifdef STEAM_API_H Steamworks::Update(); #endif if (window->KeyHit(KEY_T)) { scene = LoadMap(world, mapname); } } #ifdef STEAM_API_H Steamworks::Shutdown(); #endif return 0; }
  23. Painting on a texture on top of another results in Artifacts at the borders. https://streamable.com/hgdv1l You can download an example project here: https://1drv.ms/u/s!Aum5gwXzTrOy9WGT-qiEPXh1arTO?e=pBfovc
  24. This is interesting. I dont know this. Maybe its possible with this to load files from a server.
×
×
  • Create New...