Pleca Posted Thursday at 05:18 AM Posted Thursday at 05:18 AM Please, let’s keep both approaches. For example, in a dungeon filled with many torches, I’d use ECS for efficiency, while for a few unique objects, I’d prefer the OOP approach for simplicity. I’m with reepblue on this one. Quote
Alienhead Posted Thursday at 05:43 AM Posted Thursday at 05:43 AM I'm on a plane currently and won't go into detail, but a one script system totally deprives the ability for add-ons and extensions. Example, my player control is a solo component, if I want to add the ability for a shotgun weapon I simply add the shotgun component to the player and he can use that ability. I can further add more abilities to the player by assigning additional components. 1 Quote Alienhead Components and Software
Alienhead Posted Thursday at 05:56 AM Posted Thursday at 05:56 AM How is that well known engines such as Unity and others have worked around the issue you present and still allow multiple components?? 1 Quote Alienhead Components and Software
Josh Posted Thursday at 04:29 PM Author Posted Thursday at 04:29 PM 13 hours ago, Dreikblack said: So please do it? Are you sure this is needed? In the last build I got rid of all virtual inheritance because it does not appear to be needed for anything, and I think you said there was no problem in your previous post. Regarding components, one possible solution might be for the editor to detect base components and display them as if they were separate components. Here is an example of a base component and another component derived from that: class MyBaseComponent : public Component { Vec4 lower;//"Min color" COLOR Vec4 upper;//"Max color" COLOR void Update() { Vec4 color; color.r = Random(lower.r, upper.r); color.g = Random(lower.g, upper.g); color.b = Random(lower.b, upper.b); color.a = Random(lower.a, upper.a); GetEntity()->SetColor(color); } }; class MyDerivedComponent : public MyBaseComponent { Vec3 speed;//"Speed" void Update() { GetEntity()->Turn(speed); MyBaseComponent::Update(); } }; When you add MyDerivedComponent to an entity, tabs for MyDerivedComponent and MyBaseComponent would appear, with properties displayed in each one, as if they were two different components. The differences would be: You would not be mixing and matching different components in the editor. Combination of different components would be achieved by declaring a class that inherits another. You can't have two properties or methods with the same name, since they would overwrite each other, since they are on one object. This might solve several problems: This would retain visual separation of properties and flowgraph subobjects in the editor. This would retain separation of code in different files. Problems involving the order different component methods are executed in would go away. The component would just be a single object to access in code. Quote My job is to make tools you love, with the features you want, and performance you can't live without.
Dreikblack Posted Thursday at 04:43 PM Posted Thursday at 04:43 PM 14 minutes ago, Josh said: I think you said there was no problem in your previous post. Because i forgot to make it Object's child. As() and Self() are pretty useful. And then i would able to pass it as Object in LW5 API methods. Also i thought it would needed to GetComponent() but gladly this one works for any class. Quote Check out Slipgate Tactics demo, which is made with Ultra Engine/Leadwerks 5: https://www.leadwerks.com/community/topic/61480-slipgate-tactics-demo/
Josh Posted Thursday at 04:45 PM Author Posted Thursday at 04:45 PM Just now, Dreikblack said: Because i forgot to make it Object's child. As() and Self() are pretty useful. And then i would able to pass it as Object in LW5 API methods. Also i thought it would needed to GetComponent() but gladly this one works for any class. Okay, if you find that useful, I don't have any objection to doing this in the next build. 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without.
Dreikblack Posted Thursday at 05:28 PM Posted Thursday at 05:28 PM 51 minutes ago, Josh said: You would not be mixing and matching different components in the editor. Combination of different components would be achieved by declaring a class that inherits another. It's not an option at all for cases when you need different components for same entity. 53 minutes ago, Josh said: This would retain separation of code in different files. And again it will not since you don't do deriving for totally different components and sane persons will not hundreds derive combinations when they can do dozen components for everything already with proper system which you want to destroy without any single good reason to do so. 55 minutes ago, Josh said: Problems involving the order different component methods are executed in would go away. The component would just be a single object to access in code. Just use single component per entity without making to so it everyone else, you can do it already. Don't break what already works millions time better than you want to do. Stop ignoring GetComponent() method existence for making excuses. 1 Quote Check out Slipgate Tactics demo, which is made with Ultra Engine/Leadwerks 5: https://www.leadwerks.com/community/topic/61480-slipgate-tactics-demo/
Alienhead Posted Thursday at 08:36 PM Posted Thursday at 08:36 PM It seems like Josh's mind was made up before starting this thread anyways. Before I waste anymore time I would like to know if you plan on going through with this new system so that I may start my search for an alternate product. Quote Alienhead Components and Software
beo6 Posted Friday at 06:53 PM Posted Friday at 06:53 PM Why remove the option to create reusable components? This sounds like you want to get rid of this to force people to always reimplement everything to fit their needs for no reason. I think it worked perfectly fine for Leadwerks 4. After some thought through standards where established, many components where made in a way to be compatible. Like the 1st person script. Quite a few used my "Amnesia" - like notes script (i think). And it allowed some people to quickly put together some games. Quote
Dreikblack Posted yesterday at 12:33 PM Posted yesterday at 12:33 PM @Joshyou keep ignoring any criticism on this topic, but i will try again. Multi-components allow: To keep logic components in one place. Even if components without entities will appear (meanwhile you want to do opposite...) there is still a lot of examples like thunder - point light with components that: 1. Make light appear and with-time reduce brightness. 2. Do sound. 3. Trigger 1 and 2 on random time. All 3 components are used in a lot other cases. Entity and component being different classes in good thing - no overriding for same names, no extra bull**** when you looking for something with autocomplete. Also component may exist without entity and i use it (by creating with own method). Mix behavior and avoid tech debt aka duplicated code in this case. Some of real examples beside above: Brush entity with: Tile trigger (when unit enters in trigger) which trigger dialog component (to text for player) and also trigger Objective trigger (to make objective about finding this door complete), usable trigger - context button to open door. All of at same entity and would be longer to make with worse result if we had no multi-comp system. Padlock on door (brush with lock texture): UsableObject component - for highlighting this entity and trigger usable trigger from above by picking. Second component is RemoveObject - for removing this lock when door is open. Animated model: on signal it's start moving with Way Mover component and start animation with another component. And i would also use third component to remove entity from scene in next game, but currently it's in WayMover. Similar combo for weapons on table + they have QuakeModel component for fixing their model. Tile trigger, dilaog + SoundEffect to make sound when unit enters this trigger. Button entity: Trigger on damage component + WayMover to make move this entity on trigger. Pillar with WayMover and EnvLevel component - to hide entity when it's too close to camera Acid brush - Acid component + WayMover. In result with enough components you can make a levels without coding just by combing components. Made up by you cons: Quote With mulitple components, you have to know exactly what component you are looking for. With single one it's exactly same, even if you screw it up by mixing with entity - you NEED to know what component entity have to do anything with that. You can't do entity->health = 0 in both Lua and C++ because Component don't have and you cast it in C++ anyway (and it's easy to do currently - just use GetComponent() and in lua it will be an error if table (component) don't have it. For C++ you also can cast not to even base Class, but interface class if needed. By the way in reality you never have cases when entity have few component with same method which you want to call. Like why the hell same entity would have two different health or use()? You just do GetComponent<Interface> or GetComponent<SomeBaseComponent>(), call once whatever you want and thats it. And in Lua you use single component which have function for sure you just do in Lua without loop and knowing which exactly component is that: entity.components[1]:Use() In result nothing will be changed in that matter and problem simply does not exist. If anything, tag system for components would be helpful for Lua to determinate if abstract component have variable and functions quickly. Something like: local components = entity:GetComponentsByTag("Health") Quote One script, one entity Why it's would be bad already described in Multi-comps pros. You are too lazy to write GetEntity() it's your personal problem. Quote ECS totally throws that away and makes things far less modular and reusable. Sorry, but it's literally random bull**** of yours and i explained above how it's opposite, meanwhile new approach would break everything and make people do same stuff all over again in same scripts/components without ability to combine functionality. If you can't make combinable components it's only your own skill issue. And most likely reason why FPSPlayer and footstep components are not work together (which could be non true after another your false accusations) is how messy FPSPlayer component is - it's have too much stuff that have to be in different components. And you want all components be that bad... Quote downside of multiple components is never knowing what type of object an entity really is supposed to be. Aaaaaaaaaaand nothing would be changed for single component. In most cases entity type does not matter and when it does you just use specific component for specific entity type. And ofc. it's easy to check entity type via casting if you need. Again nothing would be changed in that matter and problem simply does not exist. Quote Any time you call a method, set a value, or get a value from another entity, a for loop is required. This is tedious and makes me want to avoid entity interactions, unless I absolutely have to do something. Entity interactions get very complicated and ambiguous Retrieving a value from another entity involves a lot of code and is ambiguous. Another example of made up issues because @Joshignores Entity::GetComponent() existence. Short conclusion: Mono-component gives no benefits at all and hurts everything that multi-components system gives, and would do big damage for both novices and experience engine by removing ability to make and combine simple and clear components, beside confusing people by combing entity and component scopes. Quote Check out Slipgate Tactics demo, which is made with Ultra Engine/Leadwerks 5: https://www.leadwerks.com/community/topic/61480-slipgate-tactics-demo/
Alienhead Posted yesterday at 02:11 PM Posted yesterday at 02:11 PM I would like to officially withdraw my opinion on this subject, I do not wish my opinion to have any sway on the outcome due to the fact I have thought long and hard on this matter and decided to move on to a different product. I bid you all a fond farewell, I've had some fun years here! 2 Quote Alienhead Components and Software
AnthonyPython Posted yesterday at 06:47 PM Posted yesterday at 06:47 PM I agree completely with dreik and reep on this matter, seems to be completely a none issue, I prefer making specialized components like a health or armor component etc, so more multi-component less than mono, instead of always doing it as a mono-component. But I do like to do it some times as a mono component from time to time so I do a mix of both. I think this is more a developers preference of how they want to approach something more than an actual issue. If ya want to do mono component tutorials that is fine, but do not try to force a very specific methodology with such a late change idea onto current developers. It would be different if this was the path you wanted to do from the start, and no one would be bothered about it but that isn't the case. Especially when as reep pointed out is too close to 1.0 release. So yea a complete none-issue. 1 Quote OS: Windows 10 Pro CPU: i3-10100 CPU @ 3.60GHz GPU: NVIDIA 2060 Super - 8 GB RAM: 32 GB
Josh Posted 5 hours ago Author Posted 5 hours ago 23 hours ago, AnthonyPython said: I prefer making specialized components like a health or armor component etc, so more multi-component less than mono Have you written such a system? I had a lot of trouble when I tried to do this. (The video will start at the right time.) This describes why I made the FPSPlayer a single script. The other issue I see is the interaction of objects. Let's say we have a function that lets a turret choose which object it wants to target. I want to find the nearest object that has a team value defined that is different from the turret's team value: function Turret:ChooseNewTarget() self.target = nil local mindistance = self.range local entities = self.entity.world:GetEntitiesInArea(self.entity.position - self.range, self.entity.position + self.range) for n = 1, #entities do if entities[n] ~= self.entity then local dist = self.entity:GetDistance(entities[n]) if dist < mindistance then for name, component in pairs(entities[n].components) do if isnumber(component.team) and component.team ~= self.team then self.target = entities[n] mindistance = dist break end end end end end end I think most people will struggle with the inner loop through the components, Even if they understand it while they are listening to me explain it in a video, and looking at code I already wrote, I don't think they will remember how to make use of it. If they do remember, I think it will slow them down dramatically and make game interactions tedious to write. This is a lot of extra overhead just to access a variable. For many people, I think this will effectively make Leadwerks script code "read-only" since they will be unable to write new code with the system: for name, component in pairs(entities[n].components) do end You also have the problem of "which value is the real value"? What if one of their scripts sets the team property to nil, but they keep getting attacked? That kind of stuff is very difficult to track down. The alternative I am proposing removes the need for the inner loop, because the properties are just attached directly to the entity object. function Turret:ChooseNewTarget() local mindistance = self.range local entities = self.world:GetEntitiesInArea(self.position - self.range, self.position + self.range) self.target = nil for n = 1, #entities do if entities[n] ~= self then local dist = self:GetDistance(entities[n]) if dist < mindistance then if isnumber(entities[n].team) and entities[n].team ~= self.team then self.target = entities[n] mindistance = dist end end end end end I think the problems of the current design are significant enough to cause perhaps a 70% dropout rate when these tutorials are viewed, whereas the proposed design will have maybe a 20% dropout rate. That's jsut a guess based on my intuition, but I think it is roughly correct. It seems like a lot of the perceived benefit of multi-components is that if you just had a set of modular gameplay components, you could construct a game just by adding components and setting properties. I have been asking for a year and a half, what are these abstract gameplay components? No one has answered me. I installed unity to find out what they did, but it turns out Leadwerks includes more stock scripts than unity. So who is going to create these modular components that allow every game to be made? I have no idea how to do this. No one can even tell me what they should even be. Lua is the only language that allows us to just do the thing that is most intuitive to most people. It seems very strange to get rid of this simple design that everyone can understand, in favor of something that seems very complicated and difficult to use. box = CreateBox(world) box.health = 100 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without.
beo6 Posted 4 hours ago Posted 4 hours ago i just watched the video and now i better understand where the idea of josh comes from. But i still think the proposed solution is wrong. As mentioned, it will remove versatility of components. Now you end up having to write a very specific component for each type. Take the example from the video and the HealthManager component: - Since you can't seperate it anymore you would end up with a HealthManagement part in the Monster, Player, Damagable Objects and so on. Its not very reusable. And if you change one thing, you would have to change it in each and any script. - About the issue with the calling order: Yes its hard to explain and would probably trick me over (however i was right of the bat able to tell why it happens. No idea why it took a week for josh) Also another thing in the examples are bad in my opinion is to check for function names. If someone adds a component with a function with the same name, and even worse if that function has a different type or amount of arguments, it will crash. So my proposal: Add a way to use dependencies between components. This is pretty default to understand for any programmer and should be easy to explain. I haven't programmed with LUA for some time so i don't know if its possible, but maybe you can do some kind of inheritence, so you could have your FPS player extend from the HealthManager. Or maybe like interfaces in other languages. If thats not possible, i guess what could work is defining what component needs another component to be called first. That way you give the responsibility of dependencies to the components and the user who is just consuming components does not have to care about this design detail. Or if its possible: Have some kind of event system. So the actual calling of component functions really only happens if all components and its functions are there. Maybe a entity.components.HealthManager:CallFunction('AddDamage', self.damage) call could do the actual call once its sure also the FPSPlayer component (and any other component) is there. Of course if its possible to hide this design detail and still use regular `entity.components.HealthManager:AddDamage(self.damage)` that would be even better. These are just some really quick ideas around the issue without removing multiple components. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.