Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Bug Instantiating prefabs by respecting scale and rotation

Discussion in 'Entity Component System' started by HStuart, Mar 25, 2024.

  1. HStuart

    HStuart

    Joined:
    Jul 30, 2015
    Posts:
    7
    Howdy. I have the below prefabs. They are identical except for rotation. I want to be able to instantiate these at different coordinates - I do not want to set rotation programmatically.



    I have a system that spawns the correct instantiated prefab at the correct position. However, all the rotations are set to zero. If I have a CorridorX and a CorridorY at different positions, they both have a rotation of zeros, but the CorridorX entity should have a rotation of 90deg about the Y axis as can be seen in the image.

    The pertinent system code snippet is below. Shouldn't
    LocalTransform.FromPosition
    respect both scale and rotation?

    Code (CSharp):
    1. EntityCommandBuffer ecb = new(Allocator.Persistent);
    2.        
    3. for (int index = 0; index < mazeProperties.MazeSegmentProperties.Length; index++)
    4. {
    5.     MazeSegmentProperties mazeSegmentProperties = mazeProperties.MazeSegmentProperties[index];
    6.  
    7.     Entity mazeSegmentPrefab = GetPrefabForMazeSegmentType(mazeSegmentProperties.SegmentType, mazeRenderConfig);
    8.     Entity mazeSegment = ecb.Instantiate(mazeSegmentPrefab);
    9.  
    10.     float3 newPosition = new float3(
    11.         mazeSegmentProperties.PathCell.x * mazeRenderConfig.MazeSegmentSize,
    12.         0,
    13.         mazeSegmentProperties.PathCell.y * mazeRenderConfig.MazeSegmentSize
    14.     ) + mazeProperties.MazeCenter;
    15.  
    16.     ecb.SetComponent(mazeSegment, LocalTransform.FromPosition(newPosition));
    17.     ecb.SetName(mazeSegment, mazeSegmentProperties.SegmentType.ToString());
    18. }
    Any help would be greatly appreciated. Thank you.
     
  2. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    838
    The LocalTransform FromXXX static methods need to construct a whole LocalTransform value, so the values that aren’t passed along are inferred to be the best default. For rotation, that’s quaternion.identity. For scale, that’s 1. If you want to preserve parts of the original entity’s LocalTransform, you might instead consider reading the rotation and scale from the prefab itself, or baking the desired rotation and scale as properties accessible to you from the point where you instantiate the entity. Either way, you would be setting a full LocalTransform value including position, rotation, and scale through the ECB all at once.
     
    Last edited: Mar 25, 2024
  3. HStuart

    HStuart

    Joined:
    Jul 30, 2015
    Posts:
    7
    Thanks for that info. This follow-up question may sound naive. Whenever I set components, do I generally need to hydrate the entire component? If this is the case, I may need to redesign my authoring scripts to bake prefab "state" data that I can access when setting components, as you suggested. Cheers
     
  4. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    838
    In some cases, you can take a reference to a component in memory through a RefRW<T> then write to the fields you want, but that doesn't apply for cases where the entity has yet to exist, like when using an entity instantiated with EntityCommandBuffer. Methods prefixed with "Add" and "Set" populate the whole component as given, so you should indeed have the requisite data somewhere else at instantiation time.