Search Unity

How to rotate a cube from within a component system?

Discussion in 'Entity Component System' started by ryancole, Nov 11, 2018.

  1. ryancole

    ryancole

    Joined:
    Oct 8, 2017
    Posts:
    18
    Hi all,

    I'm trying to learn ECS by trial and error. I'm looking at various code samples, documentation and youtube videos. I'm just messing around with the pure ECS approach. I've got an entity archetype that has a position and rotation. It renders as a cube. I've got a rotation system that I am just trying to make the cube constantly rotate in place. I've looked at the rotation sample code, from the official unity sample repo, but when I replicate the math logic for rotating I get run-time errors (something about invalid AABB result).

    Here is the code for my rotation system. Any idea what I'm doing wrong here? I'm not using the job component system.

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Entities;
    3. using Unity.Transforms;
    4. using Unity.Mathematics;
    5.  
    6. namespace CubeWorld.Systems
    7. {
    8.     public class PlayerRotationSystem : ComponentSystem
    9.     {
    10.         [Inject]
    11.         private PlayerRotationSystemData m_data;
    12.  
    13.         #region Methods
    14.  
    15.         protected override void OnUpdate()
    16.         {
    17.             var time = Time.deltaTime;
    18.  
    19.             for (var i = 0; i < m_data.Length; i++)
    20.             {
    21.                 var rotation = m_data.Rotations[i];
    22.  
    23.                 m_data.Rotations[i] = new Rotation
    24.                 {
    25.                     Value = math.mul(math.normalize(rotation.Value), quaternion.AxisAngle(math.up(), 20 * time))
    26.                 };
    27.             }
    28.         }
    29.  
    30.         #endregion
    31.     }
    32.  
    33.     public struct PlayerRotationSystemData
    34.     {
    35.         #region Values
    36.  
    37.         public readonly int Length;
    38.         public ComponentDataArray<Rotation> Rotations;
    39.  
    40.         #endregion
    41.     }
    42. }
    43.  
    I've tried other equations too, but none have managed to get the cube to rotate.
     
    Gekigengar likes this.
  2. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    I think you're missing to tell the entityManager to set your components data. Try something like:

    Code (CSharp):
    1.             var time = Time.deltaTime;
    2.             var entityManager = World.Active.GetOrCreateManager<EntityManager>();
    3.             for (var i = 0; i < m_data.Length; i++)
    4.             {
    5.                 var rotation = m_data.Rotations[i];
    6.                 var entityWithRotation = m_data.Entities[i];
    7.                 var newRotation = new Rotation
    8.                 {
    9.                     Value = math.mul(math.normalize(rotation.Value), quaternion.AxisAngle(math.up(), 20 * time))
    10.                 };
    11.  
    12.                 PostUpdateCommands.SetComponent(entityWithRotation, newRotation);
    13.             }
    14.         }
    You've got to add: [ReadOnly] public EntityArray Entites; to your PlayerRotationSystemData too.
     
  3. ryancole

    ryancole

    Joined:
    Oct 8, 2017
    Posts:
    18
    Hmm. OK. I added that new EntityArray and am using PostUpdateCommands. I'm just getting a bunch of errors when I run it. Errors mostly regarding the following ...

    Code (CSharp):
    1. Invalid AABB result
    2. UnityEngine.Graphics:DrawMesh(Mesh, Matrix4x4, Material, Int32, Camera, Int32, MaterialPropertyBlock, ShadowCastingMode, Boolean)
    3. Unity.Rendering.MeshInstanceRendererSystem:RenderBatch(Int32, Int32) (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Rendering.Hybrid/MeshInstanceRendererSystem.cs:643)
    4. Unity.Rendering.MeshInstanceRendererSystem:UpdateDynamicInstanceRenderer() (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Rendering.Hybrid/MeshInstanceRendererSystem.cs:618)
    5. Unity.Rendering.MeshInstanceRendererSystem:OnUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Rendering.Hybrid/MeshInstanceRendererSystem.cs:825)
    6. Unity.Entities.ComponentSystem:InternalUpdate() (at Library/PackageCache/com.unity.entities@0.0.12-preview.19/Unity.Entities/ComponentSystem.cs:374)
     
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    pahe and ryancole like this.
  5. ryancole

    ryancole

    Joined:
    Oct 8, 2017
    Posts:
    18
    I do have the mesh instance renderer - I'm using the prefab approach, and it's my understanding that when I add the mesh instance renderer to the prefab and then pull components off the prefab that the mesh instance renderer is included due to that.

    OK. I'll try downgrading. I'm using the 2019 alpha.
     
  6. ryancole

    ryancole

    Joined:
    Oct 8, 2017
    Posts:
    18
    5argon likes this.
  7. ryancole

    ryancole

    Joined:
    Oct 8, 2017
    Posts:
    18
    Actually, I'm not experiencing that issue. The `math.normalize` method was just returning NaN. I had to instead use `math.normalizesafe`.

    Code (CSharp):
    1. protected override void OnUpdate()
    2. {
    3.     var time = Time.deltaTime;
    4.  
    5.     for (var i = 0; i < m_data.Rotations.Length; i++)
    6.     {
    7.         var current = m_data.Rotations[i].Value;
    8.         var desired = math.mul(math.normalizesafe(current), quaternion.AxisAngle(math.up(), time));
    9.  
    10.         m_data.Rotations[i] = new Rotation { Value = desired };
    11.     }
    12. }