Search Unity

Vector 3 offset is incorrect

Discussion in 'Scripting' started by unity_gQznZcC8i2v7Mg, Jan 14, 2021.

  1. unity_gQznZcC8i2v7Mg

    unity_gQznZcC8i2v7Mg

    Joined:
    Nov 4, 2020
    Posts:
    4
    Hey guys - need some help
    I have a prefab game object that his position needs to be corrected when a specific state is being called, I use an event that adds an offset to the game object transform, the game object goes into the function and corrects his position, but the float correction is inaccurate.

    I've tried to understand what conversion the float is going through but no luck, because in different levels the float conversion behaves differently.

    here is the event

    Code (CSharp):
    1.  
    2. public class SLObjOffsetHandler : MonoBehaviour
    3. {
    4.     static Dictionary<OffsetEvent, Vector3> offsets = new Dictionary<OffsetEvent, Vector3>(){
    5.          {OffsetEvent.iceinhole, new Vector3(0f,-1.5f,0f)}
    6.    
    7.     };
    8.  
    9.  
    10.     public void HandleObjOffsetEvent(OffsetEvent offEvent)
    11.     {
    12.    
    13.         transform.position = new Vector3(transform.position.x + offsets[offEvent].x,
    14.                             transform.position.y + offsets[offEvent].y,
    15.                             transform.position.z + offsets[offEvent].z);
    16.    
    17.     }
    18. }

    The event is being called in the prefab attached script

    Code (CSharp):
    1.     public void CheckIfIceSweatIsActive()
    2.     {
    3.    
    4.         if(sweat.gameObject.activeSelf==true && fixicepos==true)
    5.         {
    6.            fixicepos=false;
    7.            //if sweat gameobject is active - set ice correction offset
    8.            ices = GameObject.FindGameObjectsWithTag("ice");
    9.            SLObjOffsetHandler offsetHandler = GetComponent<SLObjOffsetHandler>();
    10.            foreach(GameObject i in ices)
    11.            {
    12.              offsetHandler.HandleObjOffsetEvent(OffsetEvent.iceinhole);
    13.            }
    14.         }
    15.     }
     

    Attached Files:

    Last edited: Jan 14, 2021
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    You talk about an event, a prefab object, a function and a float conversion while the code snippet you posted in your screenshot does not contain anything of those mentioned things. Your whole question is very confusing. Also if you want to include code in a post, use code tags and include the code as text. Code in an image makes it so much more difficult to read the code or to reference any of your code in our responses as we can not copy any of the code. Also the code can not be found through google / search engines which makes it even less useful.

    All we can see in your screenshot is a static dictionary that looks like it has an enum as key and a Vector3 as values. We can't see how or where you use this dictionary. Note that even the dictionary is static, you can still replace, add or remove elements from the dictionary at runtime through code.

    Please be more clear about your issue. Also include the relevant code.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Bunny83 likes this.
  4. unity_gQznZcC8i2v7Mg

    unity_gQznZcC8i2v7Mg

    Joined:
    Nov 4, 2020
    Posts:
    4
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    Well, this part looks a bit strange:

    You call HandleObjOffsetEvent always on the same object while you iterating through that list of gameobjects. Is that really intended? I don't really see the point of using a foreach loop since you do not do anything with each object. If you really are only interested in calling the HandleObjOffsetEvent method as often as you have ice objects, you should have used a simple for loop. Makes the intention clear and is slightly more efficient.

    Code (CSharp):
    1.  
    2. SLObjOffsetHandler offsetHandler = GetComponent<SLObjOffsetHandler>();
    3. for(int i = 0; i < ices.Length; i++)
    4. {
    5.     offsetHandler.HandleObjOffsetEvent(OffsetEvent.iceinhole);
    6. }
    Apart from that your HandleObjOffsetEvent method could by simplified to:

    Code (CSharp):
    1. public void HandleObjOffsetEvent(OffsetEvent offEvent)
    2.     {
    3.  
    4.         transform.position += offsets[offEvent];
    5.  
    6.     }
    Which would be way more efficient. You read transform.position 3 times which means you do 3 transform lookups and call the position getter 3 times. Every time it returns the whole position but the first time you only grab the x component, the second time only y and finally z. The same thing for your offsets lookup. You do 3 dictionary lookups and each one returns the same Vector3 which you disect manually just to recombine it manually. The Vector3 struct has operators which allow you to simply combine them natually.

    Another little thing: Since your offset is essentially a constant, it's a huge waste of overhead to call your "event" x amount of times because you have x amount of objects. If that's really your intention you should simply multiply that offset by your object count and add it once. This would result in the same operation but without the need of a loop.
     
  6. unity_gQznZcC8i2v7Mg

    unity_gQznZcC8i2v7Mg

    Joined:
    Nov 4, 2020
    Posts:
    4
    Ok, even when I use a simple loop the function multiple according to how many game objects I have in the scene, if I have 5 ice game object, I use the correction of 1.5f, for each of the game objects the correction will be 1.5f*5.
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    Well, yes, that's what your code does. And that's what we would assume you actually want because that's what your code specifically does.

    If that's not what you want, you should be more clear what you actually want. Because up to this point you haven't really said that. All you said is that when a specific "state is called" (which sounds a bit weird because state means data but you can only call methods / functions) you want to offset "the" gameobject. Offsetting an object is an action. Since you add your offset to the current position, calling this method multiple times will be accumulative. You specifically call it several times, once for every "ice" object in the scene. That's literally what you're doing. So from your description it's not clear what exactly is wrong with your current behaviour and what the expected behaviour is.
     
  8. unity_gQznZcC8i2v7Mg

    unity_gQznZcC8i2v7Mg

    Joined:
    Nov 4, 2020
    Posts:
    4

    The behavior happening right now with the loop, is what I want to avoid, and now I underatand the problem.

    What I would like to happen is that the vector offset will be the same no matter how many gameobject I have in the scene
     
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    If that's the case you probably only want to check if the number of "ice" objects is greater than 0.


    Code (CSharp):
    1. ices = GameObject.FindGameObjectsWithTag("ice");
    2. SLObjOffsetHandler offsetHandler = GetComponent<SLObjOffsetHandler>();
    3. if (ices.Length > 0)
    4. {
    5.     offsetHandler.HandleObjOffsetEvent(OffsetEvent.iceinhole);
    6. }