private void SyncQuery(Entity entity,
                               ref MovementData movement,
                               ref BaseUnitMovement.Component baseMovement,
                               ref BaseUnitStatus.Component status)
        {
            if (status.State != UnitState.Alive)
            {
                return;
            }

            if (UnitUtils.IsAutomaticallyMoving(status.Type) == false)
            {
                return;
            }

            var m_diff = baseMovement.MoveSpeed - movement.MoveSpeed;
            var r_diff = baseMovement.RotSpeed - movement.RotSpeed;

            if (m_diff * m_diff < moveDiff * moveDiff &&
                r_diff * r_diff < rotDiff * rotDiff)
            {
                return;
            }

            baseMovement.MoveSpeed = movement.MoveSpeed;
            baseMovement.RotSpeed  = movement.RotSpeed;
        }
        public void OnEntityCreated(SpatialOSEntityInfo entityInfo, GameObject prefab, EntityManager entityManager, EntityGameObjectLinker linker)
        {
            Coordinates position = Coordinates.Zero;

            if (TryGetComponent <Position.Component>(ref entityManager, entityInfo.Entity, out var pos))
            {
                position = pos.Value.Coords;
            }

            Quaternion rot   = Quaternion.identity;
            Vector3    scale = Vector3.one;

            if (TryGetComponent <PostureRoot.Component>(ref entityManager, entityInfo.Entity, out var posture))
            {
                rot   = posture.Value.RootTrans.Rotation.ToUnityQuaternion();
                scale = posture.Value.RootTrans.Scale.ToUnityVector();
            }

            Dictionary <int, CompressedLocalTransform> boneMap = null;

            if (TryGetComponent <BoneAnimation.Component>(ref entityManager, entityInfo.Entity, out var anim))
            {
                boneMap = anim.Value.BoneMap;
            }

            var gameObject = UnityEngine.Object.Instantiate(prefab, position.ToUnityVector() + this.WorkerOrigin, rot);

            gameObject.transform.localScale = scale;

            Type[] types = componentsToAdd;
            if (boneMap != null)
            {
                var container = gameObject.GetComponent <PostureBoneContainer>();
                container?.SetTrans(boneMap);
            }

            if (this.IsClient == false)
            {
                if (TryGetComponent <BaseUnitMovement.Component>(ref entityManager, entityInfo.Entity, out var movement))
                {
                    entityManager.AddComponentData <NavPathData>(entityInfo.Entity, NavPathData.CreateData());
                    entityManager.AddComponentData <MovementData>(entityInfo.Entity, MovementData.CreateData(movement.Value.MoveSpeed, movement.Value.RotSpeed));
                }

                if (TryGetComponent <BaseUnitStatus.Component>(ref entityManager, entityInfo.Entity, out var status))
                {
                    if (UnitUtils.IsBuilding(status.Value.Type))
                    {
                        entityManager.AddComponentData <BuildingData>(entityInfo.Entity, BuildingData.CreateData());
                    }
                }
            }

            gameObjectsCreated.Add(entityInfo.SpatialOSEntityId, gameObject);
            gameObject.name = $"{prefab.name}(SpatialOS: {entityInfo.SpatialOSEntityId}, Worker: {this.WorkerType})";
            linker.LinkGameObjectToSpatialOSEntity(entityInfo.SpatialOSEntityId, gameObject, types);
        }
        private void MovementQuery(Entity entity,
                                   UnitTransform unit,
                                   ref MovementData movement,
                                   ref BaseUnitStatus.Component status)
        {
            if (status.State != UnitState.Alive)
            {
                return;
            }

            if (UnitUtils.IsAutomaticallyMoving(status.Type) == false)
            {
                return;
            }

            // check ground
            if (unit == null || unit.GetGrounded(out var hitInfo) == false)
            {
                return;
            }

            var rigidbody = EntityManager.GetComponentObject <Rigidbody>(entity);

            if (movement.MoveSpeed == 0.0f &&
                movement.RotSpeed == 0.0f)
            {
                return;
            }

            var trans = rigidbody.transform;

            var uVec    = trans.forward * movement.MoveSpeed;
            var moveVec = uVec * Time.fixedDeltaTime;

            //rigidbody.velocity = uVec;
            var pos = rigidbody.position;

            rigidbody.MovePosition(pos + moveVec);

            if (movement.RotSpeed != 0.0f)
            {
                trans.Rotate(trans.up, movement.RotSpeed * Time.fixedDeltaTime);
            }
        }
        private void MovementQuery(Entity entity,
                                   ref MovementData movement,
                                   ref NavPathData path,
                                   ref BaseUnitSight.Component sight,
                                   ref BaseUnitStatus.Component status,
                                   ref SpatialEntityId entityId)
        {
            movement.MoveSpeed = 0.0f;
            movement.RotSpeed  = 0.0f;

            if (status.State != UnitState.Alive)
            {
                return;
            }

            if (UnitUtils.IsAutomaticallyMoving(status.Type) == false)
            {
                return;
            }

            var unit = EntityManager.GetComponentObject <UnitTransform>(entity);

            // check ground
            if (unit == null || unit.GetGrounded(out var hitInfo) == false)
            {
                return;
            }

            if (sight.State == TargetState.None)
            {
                return;
            }

            var trans = unit.transform;
            var pos   = trans.position;

            Vector3?tgt    = null;
            Vector3 spread = Vector3.zero;

            var id = entityId.EntityId;

            if (vectorDic.ContainsKey(id))
            {
                //tgt = vectorDic[id].boidTarget;
                spread = vectorDic[id].spread;
            }

            if (tgt == null)
            {
                tgt = sight.GetTargetPosition(this.Origin, pos);
            }

            tgt = CheckNavPathAndTarget(tgt.Value, pos, unit.SizeRadius, sight.State, entityId.EntityId.Id, ref path);

            if (RangeDictionary.IsSpreadValid(spread))
            {
                var length = (tgt.Value - pos).magnitude;
                tgt += spread * Mathf.Max(1.0f, (length / RangeDictionary.SpreadSize));
            }

            var positionDiff = tgt.Value - pos;

            var forward = get_forward(positionDiff, sight.TargetRange);

            MovementDictionary.TryGet(status.Type, out var speed, out var rot);

            var isRotate = rotate(rot, trans, positionDiff);

            if (forward != 0.0f)
            {
                movement.MoveSpeed = forward * speed;
            }

            if (isRotate != 0)
            {
                movement.RotSpeed = rot * isRotate;
            }
        }