Jump to content

Rick

Members
  • Posts

    7,936
  • Joined

  • Last visited

Blog Comments posted by Rick

  1. That's interesting. Wasn't aware you have to create a pre-processor. That could for sure work then. I'd use something like Destroy() or Delete() though as Reset() makes it seem like it'll go back to the values it had on map load (which might be a cool side feature to have actually).

  2. 4 hours ago, Josh said:

    I would not consider a name change unless the new one was very good at making the brand spread faster and telling people what the product does. The name will be revealed when the Kickstarter campaign launches, which will be near the end of development. The point of the Kickstarter campaign is to launch the larger marketing campaign. GDC will come next, with a booth and maybe a lecture.

    My first speaking gig at GDC was a nightmare. I had spent threee years writing my first C++ program. Unity had just announced a free mobile version the day before. There was a bad echo in the sound system so all my words were bouncing back to my after a short delay, making it extremely difficult to speak. And there were 600 people in the audience, from Apple, EA, Microsoft, etc., and everyone hated me, thought I was crazy, or didn’t know who I was. But I did it and I am proud of myself for that.

    That happened before Leadwerks had any success. It was just an idea and I was an unproven nobody, with no track record of success. This was before Steam and before our first Kickstarter campaign. When Leadwerks 3 was launched I did not have all the contacts in the game industry that I have now. I did not know a dozen people at Valve. I was also broke. There’s a lot more I can do with the launch of 5 but at the core of that has to be a great, not good product.

    The feedback I get from you guys is going to make this great, so I am definitely listening.

    Wow I didn’t know those details. Much respect as that took massive courage to do!

  3. Yes, that would be an issue. I would expect there is 1 shared pointer per actual pointer but if it doesn't work that way then this wouldn't work. The question is does that cause other issues too? It will be interesting to see if posts happen around this entire shared pointer idea on the lua side.

    Example showing 2 shared pointers pointing to the same underlying pointer and how reset on 1 shared pointer doesn't affect the other.

    http://cpp.sh/7y4sp

  4. -- script 1
    enemy.health = enemy.health - 1
    if enemy.health <= 0 then
    	Destroy(enemy)
        enemy = nil
    end
    
    
    -- script 2
    if Exists(self.target) then
    	self.target:Hurt(50)
    end

    This is how I would want to handle it.  Exists() is a C++ function checking the shared pointer if it's valid or not. I have my opinions on which one would be easier to explain to a user.

    At this point I think my opinion is out there so I'll stop on this specific point.

  5. 11 minutes ago, Josh said:

    Setting to nil and calling collectgarbage() totally eliminates this. I really don’t like the idea of explaining to users, “well the object isn’t null but it also doesn’t exist.” Lua should be simpler than C++, not more complicated.

    In the script where you set the variable to nil you don't have to do an Exists() check just a simple nil check because in that script that variable is already nil. This only happens in the situation where the user shared the object between scripts. That's the point where you have to check if the object still exists or not because any of the scripts that may have access to it could have deleted it. Is that not a simple concept? It's something we wish we had in LE4 and have talked about getting it before but there was no solution this simple because of the way pointers were handled. Shared pointers gives that simple solution!

    Yet I don't think setting to nil and calling collectgarbage() does solve the issue. If I have a model object shared between 2 scripts and one sets it's variable to it to nil and calls collectgarbage() does the other one not still have it because it did a copy operation when it assigned it to it's local variable. That would have created 2 counts of the shared pointer so it would still stay alive would it not? Think about the tower defense situation. One tower thought it killed the enemy unit but it really didn't because the other tower still had a reference to it so it stays alive. Doesn't sound like the desired behavior in that situation or really any situation where this can happen in a game.

    If the fear is a user forgets to call Exists(obj) and the game crashes (again you should have checks in all calls I think) then that same fear exists today and we've dealt with it for a long time. At least with the Exists() function we have a way to deal with it that doesn't require jumping through hoops we have to do now to get this desired behavior.

    I personally think explaining garbage collecting to users is more complicated given that in the scenario I posted above the garbage collecting wouldn't actually delete the object because another script had a reference to it.

  6. The real benefit you're getting though is the ability to do an if check on the smart pointer to see if it really exists or not because everything created is shared between the users code and the internal engine and you want to avoid crashes like what happens today in LE4. Smart pointers are doing great at that but they now have this side effect of keeping things around when us users don't want them around anymore.

    I don't get why having a Delete() and Exists()/IsValid()/whatever is a problem to fix the issue. Seems fairly logical doesn't it? Just trying to better understand why you and the other github guy don't think so unless he doesn't understand the context in which you're using his library since most things aren't as visual as a game engine where it probably doesn't matter if the thing hangs around.

  7. This is why I mentioned the Exists() c++ function. When you reset the shared pointer you’re doing this on the c++ side of things. So you’ll probably need to check on the c++ side of things if it’s valid. So our checks on lua would be to pass our reference to the Exists() to see if that shared pointer is still valid or not. The other approach is you checking if it’s valid in all calls of using it which is probably the way to go to prevent crashes but more work for you. Not sure if that creates a side effect of the user wondering why calls aren’t doing anything so still having the Exists() function is recommended. Think of the Exists(obj) function as the if == nil check. It gives us a way to validate if the shared pointer is valid or not on objects that may be shared between scripts. A feature that in LE 4 we don't have so that's a win right there! Remember the case of the Tower Defense where 2 towers have 1 enemy unit as a target but one kills it before the other but then the other doesn't know this and tries to kill it too and the game crashes currently. We have to do workarounds to avoid that situation. With the above idea we wouldn't have to. We'd simply check if Exists(target) then.

    We'd only really ever need to use the Exists() function if we know the object is shared between scripts. That doesn't happen on every object we create so it's not as if we need to wrap everything in an Exists() check. 99% of the time we'd just call Reset(obj) obj = nil and be done with it. (Not a fan of the Reset() name though as it doesn't really give a good description of what it's doing from a users standpoint).

    I just don’t get how deleting something and expecting it to be gone is a bad idea and against user expectations. If I delete something I expect it gone.Thats the entire point of deletion and it’s how le4 works, and any other engine works so that concept itself isn’t against user expectations.

    I don’t think it’s just visual objects to right? Wouldn’t sounds have the same requirement of stopping before deletion?

     

  8. "This of course may not fit with the programming model you're trying to create, in which case probably the best way to ensure someone can't break your program by trying to do things on deleted objects is to perform additional checks internally (inside your bound methods, etc.) to make sure your shared pointer is still holding a valid pointer."

    This is what I was saying before about doing the if statement in all commands on the LE side so things don't crash. Probably a good idea anyway to avoid crashing. However, it sounds like that other guy had a fix in mind but had to go to class. Hope he provides it as it sounds like a bug he's been aware of.

    Why would it affect the entire script? That instance of the entire script should be dead at the point of deletion anyway right? I mean internally you're creating an entity object and a script object separately right? Then assigning the script object to a member of the entity? Or is the script object stored inside the entity and then yes deleting the entity should cause the script to be deleted in the destructor of the entity I would think?

  9. 38 minutes ago, Josh said:

    The object is deleted and its destructor is called but the shared_ptr somehow holds onto the pointer and keeps the same memory address. I have no idea how.

    Normally your Exists() function is a check to see if something equals nil.

    What's the negative aspect of the first part of what you said?

    I would think because the C++ side is deleting things the Lua side isn't going to know about it so the lua variable won't be nil, which is why I was thinking the Exist() function is needed because it would do the if(shared_ptr) check in C++ which should correctly show it's no longer valid.

  10. What do you mean by saying lua holds onto the invalid pointer? Do you mean that the lua variable doesn’t turn nil after Delete is called? I wouldn’t think it would given that lua variable is a shared pointer right? However if there was an Exists(obj) function that checked the lua shared ptr was valid and returns true or false then if we know a lua variable might be shared in our code like in the tower defense situation where 2 towers point to same obj then we use that Exists() to see if it’s actually valid on the c++ side

  11. Correct, but when crossing language domains (C++/LUA) we can't set it to equal nullptr in lua directly like we can in C++. That's the entire point of my post. There is now a way to do that with the Delete() example I showed. That was why I showed it. Lua now has a way to be equal to C++ in the removal of the object vs hiding or even calling garbage collecting manually, both which are pretty hacky for when you want an object gone given you don't do that from C++ to remove the object.

  12. But the above is saying if I asked you if you know German you're saying no I don't. The if statement check. Even though you really do, that check says you don't. However, as in our example with the Test class, the language is actually gone (and error happens when we try to access it's function because the memory doesn't seem to be there anymore). So why is the if check acting as it doesn't exist anymore which in the case of the Test() class shared_ptr it doesn't, but in this string case it does. You should always use the if check before trying to access a shared_ptr right? That's the benefit, that you can tell if it's valid or not anymore where straight pointers you can't.

  13. You may want to check that with any of the stuff you're currently doing as well. The following won't print because ptr doesn't pass the if check and count is 0 after the reset(). Perhaps some difference between objects and the string class? I mean you've seen it work with objects which you're creating in the engine, but this is a different usage with whatever string is doing behind the scenes. Or perhaps make_shared()?

    	shared_ptr<std::string> ptr = make_shared <std::string>("Hello.");
    
    	auto a = ptr;
    
    	long count = ptr.use_count();
    
    	ptr.reset();
    
    	count = ptr.use_count();
    
    	if(ptr)
    		cout << *(a.get());

     

  14. From my testing reset() actually removes all references.

     

    void Delete(shared_ptr<Test>& obj)
    {
    	long count = obj.use_count(); // will show 2
    
    	obj.reset();
    
    	count = obj.use_count(); // will show 0
    }
    
    int main(){
    	shared_ptr<Test> sptr(new Test("Test"));
    
    	shared_ptr<Test> ptr = sptr;
    
    	Delete(sptr);
    	//sptr = nullptr;
    
    	sptr.get()->Print();
    
    	int input;
    
    	cin >> input;
    
    	return 0;
    }

    Note the key is passing the shared_ptr by reference to the Delete() function. So you'd probably need 2 functions. The lua one we call that gets the shared pointer object we passed in and then another that takes the object by reference. This would be the case IF we can't pass by reference from lua. Not sure if that works with the bindings or not. If it does then great, only need the 1 delete.

  15. I think this is how you'd do it.

     

    #include <memory>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    class Test{
    private:
    	string name;
    public:
    	Test(string _name){
    		name = _name;
    	}
    
    	void Print(){
    		cout << name;
    	}
    };
    
    
    void Delete(shared_ptr<Test>& obj)
    {
    	obj.reset();
    }
    
    int main(){
    	shared_ptr<Test> sptr(new Test("Test"));
    
    	Delete(sptr);
    	//sptr = nullptr;
    
    	sptr.get()->Print();
    
    	int input;
    
    	cin >> input;
    
    	return 0;
    }

    You can do an if(sptr) before trying to anything with it and that still works to make sure it's valid. If you do that on the C++ side for every command then in lua it'll never fail if we have multiple variables pointing to the one we deleted. The calls simply won't do anything, but at least they won't fail. You could make another function we can check perhaps like Exists(obj) that does the if statement on the shared_ptr and if not return false else return true? Just thinking high level on that one in case we want to know on the lua side if something was deleted.

  16. 1 hour ago, Josh said:

    But then you're walking around with a variable that is no longer a valid entity, which is exactly what smart pointers seek to avoid:

    
    auto box = CreateBox()
    box:Delete()
    box:SetPosition(1,2,3)

    Moreover, one part of your code might be still using an entity when another part is done. This is why we don't have any explicit Delete(), Destroy(), Release() etc, function.

    I would assume you can make a global function that does the exact same thing as setting to nullptr. Delete(box); This way both lua and C++ can do the same thing. It's literally exactly the same thing just a more consistent interface between the 2 languages.

  17. 1 minute ago, Josh said:

    Well actually the C++ class does not need anything to delete the object. Again, you just set the variable to nullptr:

    
    auto model = CreateBox();
    model = nullptr; //poof!

    It's gone!

    I get that's the case, but I'm trying to help find a consistent interface for this between the 2 languages because I think that's a better design and has value. You could make a global DeleteEntity(e) function perhaps that does that for both C++ objects and Lua objects so people just have to know 1 thing between the 2 languages and documentation can be shared to explain it between the 2 languages.

    • Like 1
×
×
  • Create New...