Closed MRfantastic3DGamer closed 1 year ago
You can set the position using the .position
field on the InstanceData
. If you want the entity to automatically move (ie, velocity, following paths, look-at-camera) then you can also use the Path
class
There are around 10 different example scripts. You should look at them, eg moving crowd demo: https://github.com/mkrebser/GPUInstance/blob/master/Assets/Demos/crowddemo/crowddemo.cs
I looked into the demos but they all either have static position for instances or using path. there is no example of setting position of instances directly.
this is the Monobehaviour code
using System.Collections;
using System.Collections.Generic;
using GPUInstance;
using Unity.Mathematics;
using UnityEngine;
using Random = UnityEngine.Random;
public class MarchPeople : MonoBehaviour
{
public Camera FrustumCullingCamera;
public GPUSkinnedMeshComponent character;
public double GlobalTimeSpeed = 1.0;
private int2 grid = new int2(100, 100);
private MeshInstancer m;
private SkinnedMesh[] instances = new SkinnedMesh[10000];
void Start()
{
// Initialize character mesh list
int hierarchy_depth, skeleton_bone_count;
List<GPUSkinnedMeshComponent> characters = new List<GPUSkinnedMeshComponent>();
characters.Add(character);
var controllers = GPUSkinnedMeshComponent.PrepareControllers(characters, out hierarchy_depth, out skeleton_bone_count);
// Initialize GPU Instancer
this.m = new MeshInstancer();
this.m.Initialize(max_parent_depth: hierarchy_depth + 2, num_skeleton_bones: skeleton_bone_count, pathCount: 2);
// Add all animations to GPU buffer
this.m.SetAllAnimations(controllers);
// Add all character mesh types to GPU Instancer
this.m.AddGPUSkinnedMeshType(character);
// Do stuff
for (int i = 0; i < 10000; i++)
{
var mesh = character;
var anim = mesh.anim.namedAnimations["walk"];
instances[i] = new SkinnedMesh(mesh, this.m);
instances[i].mesh.position = new Vector3(x: i / 100, 0, i % 100);
instances[i].SetRadius(1.75f); // set large enough radius so model doesnt get culled to early
instances[i].Initialize();
instances[i].SetAnimation(anim, speed: 1.4f, start_time: Random.Range(0.0f, 1.0f)); // set animation
instances[i].UpdateAll();
}
}
void Update()
{
Ticks.GlobalTimeSpeed = this.GlobalTimeSpeed;
this.m.FrustumCamera = this.FrustumCullingCamera;
{
var skinnedMesh = instances[0];
Debug.Log(skinnedMesh.mesh.position);
var pos = new Vector3(skinnedMesh.mesh.position.x, 0,
skinnedMesh.mesh.position.z + Time.deltaTime);
instances[0].mesh.position = pos;
// log the supposed position of first instance
Debug.Log(instances[0].mesh.position);
instances[0].UpdateAll();
}
for (var i = 1; i < instances.Length; i++)
{
var skinnedMesh = instances[i];
var pos = new Vector3(skinnedMesh.mesh.position.x, 0,
skinnedMesh.mesh.position.z + Time.deltaTime);
skinnedMesh.mesh.position = pos;
instances[i] = skinnedMesh;
instances[i].UpdateAll();
}
this.m.Update(Time.deltaTime);
}
}
but the instances are stuck in the same place
When you manually modify an instance, you will need to tell the GPU what has been modified.
ie,
instance.DirtyFlags = DirtyFlag.Position | DirtyFlag.Rotation | DirtyFlag.Scale;
will tell the compute program to update the position, rotation, scale of an instance.
There are 'DIrtyFlags' for every property!
That being said, if you are just setting a velocity, I would recommend using a path! They can simulate constant motion! And this library will allow you to automatically calculate the full TRS transform of the instance at any time if you need it!
Also, the instancemeshdemo.cs has an example of the position being changed every frame! It parents all of the cube instances to a single instance (which allows for manual adjustment of its transform) which allows you to transform the entire scene in real-time!
It worked thanks a lot for your help.
Updating position every frame reduced the performance from 60fps to about 35fps for my example with 10k instances but it is still way better than all the other options i have explored, and i am pretty sure unity's official DOTS animation system (whenever it comes) is not going to be this performant.
That being said, if you are just setting a velocity, I would recommend using a path! They can simulate constant motion! And this library will allow you to automatically calculate the full TRS transform of the instance at any time if you need it!
Yes, that would be great but setting up path for all the different AIs is going to be difficult as i also have to set up a conversion system to make it work with DOTS.
This library is thread safe, does it help if you set the positions in multiple threads?
Although, it will still have to push 10k transform updates to the GPU every frame which is a lot.
Another area that may be worth investigating is seeing if you can put your DOTS simulation at a slower fixed time step and then allowing instances to get interpolated to positions via paths. You could at least try this for entities that are far away! 10k entities doing physics and ai every frame is quite heavy!
Seems you figured out your issue, so I will close this!
Hi, I want to use it as a method of introducing animations in dots as the official animation package is still not ready. so i want to place the instances myself in code. but setting position gives an error in as that is only available for billboards. is there a way to set position of instances in code.