Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. We're looking for your feedback on the platforms you use and how you use them. Let us know!
    Dismiss Notice
  4. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  6. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  7. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  8. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

TransformMatrixComponent and Scaling?

Discussion in 'Entity Component System and C# Job system' started by Rennan24, Mar 28, 2018.

  1. Rennan24

    Rennan24

    Joined:
    Jul 13, 2014
    Posts:
    27
    I was messing around with the new ECS and I couldn't figure out how to change the scale of the TransformMatrixComponent. It doesn't look like Unity.Transforms has any Components for scale, all I saw was the RotationComponent and the PositionComponent. Am I missing something or is it just because it hasn't been implemented yet?
     
  2. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    117
    It hasn't been implemented yet AFAIK. If you in need a transform system which supports scaling (without hierarchy), I can post some code here.
     
    Rennan24 likes this.
  3. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    606
    i have used the transform matrix component for the instance renderer, but have only used it indirectly through position, I guess you. CAn just mess with it directly?
     
    Rennan24 likes this.
  4. Rennan24

    Rennan24

    Joined:
    Jul 13, 2014
    Posts:
    27
    If you want to post some code here I would greatly appreciate it :)

    Yeah you can really only mess with the Position and Rotation so far it seems like, hopefully as the ECS package keeps getting updated, Unity will put the Scaling component in! ;)
     
  5. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    606
    That's not what I meant. I think you should be able to set the value of the transform matrix component directly (without using unity's build in systems for position and rotation) - this would give you access to scale
     
  6. Rennan24

    Rennan24

    Joined:
    Jul 13, 2014
    Posts:
    27
    Oh I see what you mean, I started tinkering around with it and came up with this!

    Code (CSharp):
    1. using Unity.Collections.LowLevel.Unsafe;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Mathematics;
    5. using Unity.Transforms;
    6. using Unity.Jobs;
    7. using UnityEngine;
    8.  
    9. public class ScaleComponent : ComponentDataWrapper<Scale> { }
    10.  
    11. [System.Serializable]
    12. public struct Scale : IComponentData
    13. {
    14.     public float3 Value;
    15. }
    16.  
    17. [UnityEngine.ExecuteInEditMode]
    18. public class TransformSystem : JobComponentSystem
    19. {
    20.     struct TransformGroup
    21.     {
    22.         [ReadOnly]
    23.         public ComponentDataArray<Position> Positions;
    24.  
    25.         [ReadOnly]
    26.         public ComponentDataArray<LocalRotation> Rotations;
    27.  
    28.         [ReadOnly]
    29.         public ComponentDataArray<Scale> Scales;
    30.  
    31.         public ComponentDataArray<TransformMatrix> Transforms;
    32.         public int Length;
    33.     }
    34.  
    35.     [Inject]
    36.     TransformGroup transformGroup;
    37.  
    38.     [ComputeJobOptimization]
    39.     struct TransformGroupJob : IJobParallelFor
    40.     {
    41.         [ReadOnly]
    42.         public ComponentDataArray<Position> Positions;
    43.  
    44.         [ReadOnly]
    45.         public ComponentDataArray<LocalRotation> Rotations;
    46.  
    47.         [ReadOnly]
    48.         public ComponentDataArray<Scale> Scales;
    49.  
    50.         public ComponentDataArray<TransformMatrix> Transforms;
    51.  
    52.         public void Execute(int i)
    53.         {
    54.             Transforms[i] = new TransformMatrix
    55.             {
    56.                 Value = math.mul(math.rottrans(Quaternion.Euler(Rotations[i].Value.value.xyz), Positions[i].Value), math.scale(Scales[i].Value))
    57.             };
    58.         }
    59.     }
    60.  
    61.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    62.     {
    63.         var transformJob = new TransformGroupJob
    64.         {
    65.             Transforms = transformGroup.Transforms,
    66.             Positions = transformGroup.Positions,
    67.             Rotations = transformGroup.Rotations,
    68.             Scales = transformGroup.Scales,
    69.         };
    70.  
    71.         return transformJob.Schedule(transformGroup.Length, 64, inputDeps);
    72.     }
    73. }
    74.  
    Probably not the most fastest running code but it does let me tinker with Entities until Unity decides to add a Scale Component to the ECS. Another annoying thing that I noticed with the Entity debugger was that when you disable a system, after hitting play, that system would re-enable itself. Also I didn't actually know how to reorder the systems so that my system happens before Unity's own TransformSystem, since they create a new matrix completely invalidating the one I made in this new system.
     
  7. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    606
    I have not looked into your implementation, but I think that if you want to avoid interference with Unity's Transform System, you should avoid their built-in position, rotation components and roll your own ones.

    This way their Transform System should not kick-in at all and you can deal with your own "MyPosition", "MyRotation", "MyScale" components in your own system, i.e. setting the TransformMatrix.
     
    Rennan24 likes this.
  8. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    117
    Here is the gist as promised. I fiddled a little with the code as I removed my namespaces and put all the components into one file. Let me know if it works. Please also note that you now need an "Active" component on each object you want to render.
    https://gist.github.com/JoeCoo7/f497af9b1ba2ab5babae3060635a9c6a
     
    Last edited: Mar 30, 2018
  9. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    558
    Looks pretty clean!

    One minor question / comment - I think it's safe to pass the injection group struct to a job? Saves having to type out all the arrays / permissions twice!
     
    DwinTeimlon likes this.
  10. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    117
    Yes, that is a good suggestion.
     
  11. jj_unity328

    jj_unity328

    Joined:
    Jun 7, 2018
    Posts:
    18
    I had the same idea and all worked fine at first but then I had memory overflow and whatnot when I tried to spawn more entities. Be cautious, do tests!
     
  12. Afonso-Lage

    Afonso-Lage

    Joined:
    Jul 8, 2012
    Posts:
    70
    This doesn't sounds to be a good idea, since when you write the permissions on a Job and then mark it as a
    [BrustCompile]
    (previous
    [JobComputeOptimization]
    ) the Brust Compile will take a look on those permissions, create some context, do some optimizations and safety handling based on that. If you just pass the entire group you are basically using it as a simple Job, without much of the advantages of using brust compiler.

    Remember that on of the main goals of Brust Compiler is to use SIMD instructions, which needs to be heavy tied with linear memory layout. That's also the same reason why they are working with special types like
    StructOfArrays
    , which I didn't fully understood yet..
     
  13. NudelGames

    NudelGames

    Joined:
    May 9, 2017
    Posts:
    1
    Also wanted to post my solution, which modifies the TransformMatrix from the TransformSystem. So it will work with all combinations of Position, Heading, Rotation, etc.

    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Entities;
    3. using Unity.Mathematics;
    4. using Unity.Transforms;
    5.  
    6. [System.Serializable]
    7. public struct Scale : IComponentData
    8. {
    9.     public float3 Value;
    10. }
    11. public class ScaleComponent : ComponentDataWrapper<Scale> { }
    12.  
    13. [UpdateAfter(typeof(TransformSystem))]
    14. public class ScaleSystem : ComponentSystem
    15. {
    16.     public struct ScaleGroup
    17.     {
    18.         public readonly int Length;
    19.         [ReadOnly] public ComponentDataArray<Scale> Scale;
    20.         public ComponentDataArray<TransformMatrix> TransformMatrix;
    21.         public SubtractiveComponent<VoidSystem<TransformSystem>> VoidSystemTransformSystem;
    22.         public SubtractiveComponent<VoidSystem<ScaleSystem>> VoidSystemScaleSystem;
    23.     }
    24.     [Inject] public ScaleGroup Scale;
    25.  
    26.     protected override void OnUpdate()
    27.     {
    28.         for (int i = 0; i < Scale.Length; i++)
    29.         {
    30.             var scale = Scale.Scale[i].Value;
    31.             Scale.TransformMatrix[i] = new TransformMatrix { Value = math.mul(Scale.TransformMatrix[i].Value, new float4x4(scale.x, 0, 0, 0, 0, scale.y, 0, 0, 0, 0, scale.z, 0, 0, 0, 0, 1)) };
    32.         }
    33.     }
    34. }
     
  14. Caiuse

    Caiuse

    Joined:
    Jan 6, 2010
    Posts:
    29
    @NudelGames Thank you for this, the cleanest solution that doesn't involve modifying the ECS source.

    And for anyone looking to preset the scale value:
    Code (CSharp):
    1.  
    2.         var scaleComponents = new NativeArray<Scale>(scaleCount, Allocator.TempJob);
    3.         var setScaleJob = new MemsetNativeArray<Scale>()
    4.         {
    5.             Source = scaleComponents,
    6.             Value = new Scale()
    7.             {
    8.                 Value = new float3(1f)
    9.             }
    10.         }.Schedule(scaleCount, 64);
    11.  
     
  15. omegabytestudio

    omegabytestudio

    Joined:
    Nov 9, 2015
    Posts:
    72
    Hey Caiuse,


    I just started playing with Pure ECS, and I don't really get your code.

    What do you mean by preset abd how do you use it?

    I'm using NudelGames Code to spawn trees that are different size

    Code (CSharp):
    1. entityManager.SetComponentData(tree, new Scale { Value = new float3(ecosystemSettings.treeSX, ecosystemSettings.treeSY, ecosystemSettings.treeSZ) });
    Should I use your method?