0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Unity]マウスポインタでECSエンティティをさわる(実行時)

Last updated at Posted at 2021-03-22

動作確認環境

Unity 2020.02
Entities 0.17.0

前提

さわる対象のEntityはPhysics Shape相当(Colliderでもさわれる)がないとだめです。
#Physics Bodyは不要の簡易版

ソースコード

2パターン。(挙動的には同一のもの)
・Monobehavior経由
・ECS、Job、Burstで実行(無駄に長い)
 カメラ情報を取得するためにMonobehaviorを使います。

MouseTouchEntityFromMonobehavior.cs
	[SerializeField] Camera xCamera = default;

	const float RAYCAST_DISTANCE = 1000;
	PhysicsWorld physicsWorld => World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>().PhysicsWorld;
	EntityManager entityManager => World.DefaultGameObjectInjectionWorld.EntityManager;
	void LateUpdate()
	{
		var screenPointToRay = xCamera.ScreenPointToRay(position);
		var rayInput = new RaycastInput
		{
			Start = screenPointToRay.origin,
			End = screenPointToRay.GetPoint(RAYCAST_DISTANCE),
			Filter = CollisionFilter.Default
		};
		if (!physicsWorld.CastRay(rayInput, out RaycastHit hit)) return;
		var selectedEntity = physicsWorld.Bodies[hit.RigidBodyIndex].Entity;
		// ↑ マウスがあたったエンティティ(単体)
		// CastRayの2個目の引数でNativeList<RaycastHit>を入れてあげれば
		// Start-End間のEntitiesを取れる。(検証してないけど)

		// あたったコンポーネントにアクセッス!
		var renderMesh = entityManager.GetSharedComponentData<RenderMesh>(selectedEntity);
	}
MouseTouchEntityFromJob.cs
    public class MouseTouchEntityFromJob : MonoBehaviour, IConvertGameObjectToEntity
    {
        [SerializeField] Camera xCamera = default;
        MouseTouchEntityFromJobSystem system => World.DefaultGameObjectInjectionWorld.GetExistingSystem<MouseTouchEntityFromJobSystem>();
        void IConvertGameObjectToEntity.Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
        {
            dstManager.AddComponentData(entity, new MouseTouch() {});
        }
        void Start()
        {
            system.xCamera = xCamera;
        }
    }
    public struct MouseTouch : IComponentData {}
	public struct HitTargetData
	{
		public Entity Entity;
		public int Hit;
	}

    public class MouseTouchEntityFromJobSystem : SystemBase
    {
        public Camera xCamera = default;
        const float RAYCAST_DISTANCE = 1000;
        public NativeArray<HitTargetData> MouseHitData;
        BuildPhysicsWorld m_BuildPhysicsWorldSystem;
        EndFramePhysicsSystem endFramePhysicsSystem;
        EntityQuery m_MouseGroup;

        public MousePickSystem() 
        {
            // 気持ち悪かったらOnStartRunning()内でもいい好きにして!
            MouseHitData = new NativeArray<HitTargetData>(1, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            MouseHitData[0] = new HitTargetData();
        }
        protected override void OnStartRunning()
        {
            // OnCreate()でもいい。好きにして!
            m_BuildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
            endFramePhysicsSystem     = World.GetOrCreateSystem<EndFramePhysicsSystem>();
            m_MouseGroup = GetEntityQuery(new EntityQueryDesc { All = new ComponentType[] { typeof(MouseTouch) } });
        }
        protected override void OnUpdate()
        {
            var handle = JobHandle.CombineDependencies(Dependency, endFramePhysicsSystem.GetOutputDependency());
            if (Input.GetMouseButton(0))
            {
                MouseTouchExecute(ref handle);
                PaintJobHandle = handle;
                handle.Complete();
            }
            Dependency.Complete();
            if(MouseHitData[0].Hit == 1)
            {
				// あたったコンポーネントにアクセッス!
				var renderMesh = EntityManager.GetSharedComponentData<RenderMesh>(MouseHitData[0].Entity);
            }
        }
        protected override void OnDestroy()
        {
            if (MouseHitData.IsCreated) MouseHitData.Dispose();
        }

        void MouseTouchExecute(ref JobHandle handle)
        {
            var screenPointToRay = xCamera.ScreenPointToRay(Input.mousePosition);
            handle = new Touch
            {
                physicsWorld = m_BuildPhysicsWorldSystem.PhysicsWorld,
                SpringData = MouseHitData,
                RayInput = new RaycastInput
                {
                    Start = screenPointToRay.origin,
                    End = screenPointToRay.GetPoint(RAYCAST_DISTANCE),
                    Filter = CollisionFilter.Default
                },
            }.Schedule(handle);
        }
        [BurstCompile]
        struct Touch : IJob
        {
            [ReadOnly] public PhysicsWorld physicsWorld;
            public NativeArray<HitTargetData> SpringData;
            public RaycastInput RayInput;

            public void Execute()
            {
                if (physicsWorld.CastRay(RayInput, out Unity.Physics.RaycastHit rayInput))
                {
                    RigidBody hitBody = physicsWorld.Bodies[rayInput.RigidBodyIndex];
                    SpringData[0] = new HitTargetData
                    {
                        Entity = hitBody.Entity,
                        Hit = 1,
                    };
                }
                else
                {
                    SpringData[0] = new HitTargetData 
                    {
                        Hit = 0,
                    };
                }
            }
        }
    }

参考資料

https://github.com/reeseschultz/ReeseUnityDemos
https://github.com/Unity-Technologies/EntityComponentSystemSamples

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?