Ruskul's Forum Posts

  • Ashley, could you tell me? Am I able to cache world info, or do I need to define it in every method I create?

    	const wi = this.GetWorldInfo(); 
    

    Also, why not just simply refer to:

    	this._worldInfo
    

    I see the above line defined in the manual, but I can't find an example in official behaviors other than repeated calls to GetWorldInfo() in every function that needs it (mostly). I see some functions where wi gets passed to another function via a parameter. For example (in sprite plugin):

    Draw(renderer) {
     const texture = this._currentTexture;
     if (texture === null)
     	return;
     renderer.SetTexture(texture);
     const wi = this.GetWorldInfo();
     if (wi.HasMesh())
     	this._DrawMesh(wi, renderer);
     else
     	this._DrawStandard(wi, renderer)
     }
    
     _DrawStandard(wi, renderer) {
     	let quad = this._bquadRef;
     	if (this._runtime.IsPixelRoundingEnabled())
     		quad = wi.PixelRoundQuad(quad);
     	renderer.Quad4(quad, this._currentQuadTex)
     }
    
     _DrawMesh(wi, renderer) {
     	const transformedMesh = wi.GetTransformedMesh();
     	if (wi.IsMeshChanged()) {
     		wi.CalculateBbox(tempRect, tempQuad, false);
     		let quad = tempQuad;
     		if (this._runtime.IsPixelRoundingEnabled())
     			quad = wi.PixelRoundQuad(quad);
     		transformedMesh.CalculateTransformedMesh(wi.GetSourceMesh(), quad, this._currentQuadTex);
     		wi.SetMeshChanged(false)
     	}
     	transformedMesh.Draw(renderer)
     }
  • I'm a bit confused as I dig around official behaviors.

    I see examples of both the following:

    	const wi = this._inst.GetWorldInfo();
    
    	//some other place in the same behavior
    	const wi = this.GetworldInfo();
    
    
    

    In the manual, this._inst is defined as:

    Reference to the Instance representing this instance in the runtime. This allows access to Construct's built-in runtime features for instances.

    If I am defining a behavior and working inside the Instance.js file, are those 2 lines of code synonymous? For that matter then, wouldn't the following work:

    	const wi = this._worldInfo;
    

    Or do I completely misunderstand?

    I'm just confused why both are used (reference custom movement).

    Yes this was removed yearsss ago

    Well, that checks out lol, last time I sent a pm was years ago.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Have you added this to the gihub suggestions? I didn't see it over there but wanted to double check.

    Data is a major reason why sometimes I choose unity over construct. Though usually it's due to lack of abstraction.

    Solving the nested families issue, or allowing cross family picking would also improve working with data without even specifically addressing data issues.

    I thought there used to be a way to PM people on the website, but I can seem to find it. Was it disabled?

  • Heh, this had come up before on the older suggestions platform:

    https://www.construct.net/en/forum/construct-3/general-discussion-7/suggestion-custom-data-feature-176502

    I also think this would be very useful in production environments, though, it looks like this is to address the global space, if I understand correctly. In order to be able to communicate from family to family, per instance, you need to be able to have data that is common across a particular plugin. So an obj in both FamA and FamB could set a common var through FamA and then later FamB could use that info in whatever way it needs to.

    I totaly agree that its a great practice to keep code isolated and performing its own thing, but games often require coupled code (platformer and Solid is a grand built in example) and a common data shared between all instances and accessible by any family would solve that issue. Z order, opacity, and color can be used to facilitate communication, but those have other uses obviously.

  • It seems the best way currently, is to forget instance variables, and use JSON or dictionaries as a form of instance variables.

    That's typically what I've ended up doing, it has its pros and cons, but personally I think there are far more pros to use a dictionary than instance vars!

    Yeah, I like dictionaries too for those reasons. I never have had or thought to put them in a family. Can you elaborate on the benefits of that? currently I'm using overboy's data+ so I can have them on instances in order to avoid foreach picking loops. But, obviously that means I lose the benefit of two families being able to reference the same dictionary.

    The workarounds are all decent and simple to use, but they all end up requiring for each loops. Hierarchies, compound objects, uid family shifting (where you simply pick another family by UID), are all viable until you have performance bottlenecks.

    I fear that high count objects simply have to have as little abstraction as possible, even if it means recreating the same behaviors multiple times. Fun facts, I even noticed family events take a little longer to run than the same thing on an object with equal counts, etc... The performance was maybe only a 10% difference, so not a concern for me given other high costs, but still fun to notice.

    I think that in the end I am probably going to go with ease of programing and simply design the game around a smaller object count. I'll be able to simply get the core of the game complete and then see how many objects it tolerates and then go from there.

    In unity or unreal, having several 1000 objects can start to bog things down, but you can get crazy insane performance for millions of objects if you go with ECS (an alternate paradigm for games that is neither oop or component based, but allows modern AAA games to have things like schooling fish or flocking birds by the thousands). The downside is that it takes more work to set up, has to be custom tailored, and is difficult to make modular or extend - so it ends up being a real pain every time, regardless of how similar two sets of objects are. I think the case stands here in similar fashion. If you have 100 dynamic/complex objects, performance differences between an abstracted framework running a foreach and a custom optimized solution will be meaningless. If you want 1000s, you start to see the benefits, but optimizations start to really be case specific.

  • > Why does that matter? Your workaround is running every tick

    I'm guessing one overlapping check + one variable check is less costly than two overlapping checks.

    Definitely, the performance difference will depend on how many objects you have, but it will remain true for even small object counts (though, the philosophy of when to optimize should be considered in small count cases)

  • That makes sense. Thanks for the details ASHLEY. indeed, it is clear now.

    If you had any thoughts on the below, I would great appreciate it.

    If nested families takes too much work and isn't a priority, there is one thing that may be easy to implement that would alleviate part of the issue (namely communicating between families). Currently, the easiest way to to communicate between families is to use a common variable (z order, opacity, color, etc...). But that won't work if need those for what they were made for. The following suggestion is useful not just in context of the current issue, so deciding to have nested families in the future wouldn't make this suggestion obsolete.

    If we could extend/define our own common variables for a plugin, then would could use those between families to communicate and aid in picking. For example, if I could create an instance variable that would then be available to every single instance, regardless of family, then I could use that to share data between them. Basically a type of custom common variable.

    The other option (which also has its own beifits even if nesting is later added) is to allow families to share instance variables or behaviors between them. Currently construct knows when a behavior called "platformer" already exists on an object type and won't allow us to add it again without it being a different name. Would it be easy to simply allow both families to refer to the same behavior/var? Then defining shared functionality would be as easy as naming the behavior or variable the same name accross families and not preventing it. Since construct prevents the same name, I am assuming that a particular conflict could be leveraged as a useful feature. You would still have to potentially repeat code in this setup, but using a shared variable would be more akin to defining an interface.

    I made the argument that nesting is the most important feature on the github post, but I think that only applies to managing larger projects or advanced use cases where complexities of abstraction are the most pressing issue. But I understand the benefits of this would not be apparent to many beginners.

    I would add, that for me at least, if changing families to allow for nesting made all family use less performant at game run time, I wouldn't like that either. lol

    As it stands the foreach workaround and uid picking isn't terribly inconvenient, but it does become a performance drain, and if the performance drop from that is unbearable I can at least try other methods.

  • You can say if A is overlapping B then set to 1. If A is not overlapping B then set to 0. So the first one but right-click inverted.

    That duplicates the collision check though, right?!

  • dop2000 good suggestion. I had it combined, and for whatever reason uncombined it and I don't remember why :/

  • Lets say I have:

    A overlaps B -> set A.somevar to 1

    Else -> set B.somevar to 0

    The else statement will never run if a single A is overlapping B. What I want it to set any remaining A not picked by the first event and set somevar to 0.

    I can't afford to duplicate collision checks or run for eachs. Both are costly from a performance standpoint so the best I have is:

    EveryTick

    ---Set A.somvar to 0;

    A overlaps B

    ---Set A.somvar to 1;

    A.somvar = 1?

    ---Do the things

    A.somvar = 0?

    ---Do the other things.

    Its seems verbose, has more events than it should, and still duplicates the number of checks. Is there now built in In case of A do this or B do that?

  • I am sure this has been asked before... but...

    Simple question: Why can't a family be in a family? Why can't one family know all objects in it are also in another family? As it stands, you can't put an object into a family that has the same variable as another which obviously means construct knows what families an object is in or not in.

    I think everyone understands the reason why, so I'll not get into detail here, but if you don't I'll try to explain.

    The basic idea is that, while you can recreate the effect of family in family, you often have to duplicate functionality across multiple families(bad programing period.) or have conditional branches based on object type variable stored in the family (extremely bad programing technique, full stop page break period.) This isn't to say conditional branches are bad - but they are in this case, because you can easily find that everytime you have an event for FamA you need a series of sub events to pick for type (meaning you are repeating yourself, and creating a terrible codebase). Now you have a project where everytime you add a new type, you have to hunt down all the different sub picking events to add to it and woe to those who forget where. Then removing a type involves the same thing.

    The above isn't a opinion as much as it is an accepted industry truth for the last 30 years. Those who disagree simply haven't felt the pains of managing such a product at an appropriate scale long term.

    The work arounds for family in families involve techniques that make a project harder to scale, increase difficulty of maintaining codebase, etc...

  • Okay, it seems this method does not work consistently. For example if I have 2 sprites, and two families and I put sprite A in famA and sprite AB in famA and famB, depending on the order of creation, it may work or may not. In the case where the family transfer doesn't work, when famA gets picked, but the sprite is not in famb, object AB will be picked when the family transfer happens. But when the same condition picks famA and sprite AB gets picked, the family transfer won't work.

    Simply changing which sprite is in both families will cause it to work suggesting to me some sort of internal ordering that plays a part. On the other hand, if both objects are in famA and famB it will work, but that sort of defeats the purpose. If all objects in A are in B and vica verca, there is no reason to have the families be separate.

  • In regards to the else, I understand why. Else only runs if no objects meet the first condition.

    Is there a clever way to simply have a way to invert the current sol?

    It seems silly to either run a for each or double a collision test when technically, you should already have everything you need.

    Maybe we need a systme condition that is "alternatively", or "alt". Bacially, do this to the inversion of the current sol, after doing the other thing to which objects met the condition.