/// <summary>
        /// Move the character with the Srt (CPMA based) algorithm.
        /// </summary>
        /// <param name="initialVelocity">The initial velocity to use</param>
        /// <param name="direction">The movement direction</param>
        /// <param name="settings">The movement settings</param>
        /// <param name="dt">Delta time</param>
        /// <returns>Return the new position</returns>
        private static float3 SrtMove(float3 initialVelocity, float2 initialDirection, float3 direction, DefStGroundRunSettings settings, CharacterControllerState state,
                                      float dt)
        {
            // Fix NaN errors
            direction = SrtFixNaN(direction);

            // Set Y axe to zero
            initialVelocity.y = 0;

            var previousSpeed = math.length(initialVelocity);
            var friction      = SrtGetFrictionPower
                                (
                previousSpeed,
                settings.FrictionSpeedMin, settings.FrictionSpeedMax,
                settings.FrictionMin, settings.FrictionMax
                                );

            var angleInvertedDir = 1 - state.AngleDir.y;

            if (math.abs(angleInvertedDir) > 0.4f)
            {
                friction *= math.clamp(math.abs(angleInvertedDir), 0.4f, 1f);
            }

            var velocity = SrtApplyFriction(initialVelocity, direction, friction, settings.SurfaceFriction, settings.Acceleration,
                                            settings.Deacceleration, dt);
            var wishSpeed = math.length(direction) * settings.BaseSpeed;

            if (float.IsNaN(wishSpeed))
            {
                wishSpeed = 0;
            }

            var strafeAngleNormalized = SrtGetStrafeAngleNormalized(direction, math.normalize(initialVelocity));

            if (wishSpeed > settings.BaseSpeed && wishSpeed < previousSpeed)
            {
                wishSpeed = math.lerp(previousSpeed, wishSpeed, math.max(math.distance(wishSpeed, previousSpeed), 0) * dt);
            }


            if (initialDirection.y > 0.5f)
            {
                if (previousSpeed >= settings.BaseSpeed - 0.25f)
                {
                    wishSpeed = settings.SprintSpeed;

                    settings.Acceleration = 6f;
                }
            }

            if (state.AngleDir.y >= 0)
            {
                wishSpeed *= math.clamp(state.AngleDir.y + 0.1f, 0.1f, 1f);
            }

            velocity = SrtAccelerate(velocity, direction, wishSpeed, settings.Acceleration, math.min(strafeAngleNormalized, 0.25f), dt);

            var nextSpeed = math.length(math.float3(velocity.x, 0, velocity.z));

            if (previousSpeed > nextSpeed && nextSpeed < settings.BaseSpeed &&
                strafeAngleNormalized > 0.1f && strafeAngleNormalized < 0.9f)
            {
                velocity.y = 0;

                velocity = Vector3.Normalize(velocity) * math.lerp(nextSpeed, previousSpeed, math.max(1 - strafeAngleNormalized, 0.8f));
            }

            return(velocity);
        }
Beispiel #2
0
        public override void Create(Entity entity)
        {
            Debug.Assert(GameObject != null, "GameObject != null");
            Debug.Assert(GameObjectEntity.Entity == entity, "GameObjectEntity.Entity == entity");


            var characterController = GameObject.GetComponent <CharacterController>();

            characterController.center           = Vector3.up * 0.9f;
            characterController.radius           = 0.4f;
            characterController.stepOffset       = 0.4f;
            characterController.height           = 2f * 0.9f;
            characterController.slopeLimit       = 75;
            characterController.detectCollisions = false;

            AddDefaultComponents(entity);

            if (Player.IsCreated)
            {
                EntityManager.AddComponentData(entity, new CharacterPlayerOwner
                {
                    Target = Player.WorldPointer
                });
            }

            EntityManager.AddComponentData(entity, new CharacterControllerState(false, false, false, Vector3.up));
            EntityManager.AddComponentData(entity, StormiumCharacterMvData.NewBase());
            EntityManager.AddComponentData(entity, new StormiumCharacterMvProcessData());

            ShareManager.SetShareOption(entity, typeof(CharacterPlayerOwner), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(CharacterControllerState), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(StormiumCharacterMvData), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(StormiumCharacterMvProcessData), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);

            /*// Add switcher
             * {
             *  var actionEntity = EntityManager.CreateEntity
             *  (
             *      typeof(StActionTag),
             *      typeof(StActionOwner),
             *      typeof(StActionSlot),
             *      typeof(StActionDualSwitch)
             *  );
             *
             *  var actionType = typeof(StActionDualSwitch);
             *
             *  EntityManager.SetComponentData(actionEntity, new StActionTag(TypeManager.GetTypeIndex(actionType)));
             *  EntityManager.SetComponentData(actionEntity, new StActionOwner(entity));
             *  EntityManager.SetComponentData(actionEntity, new StActionSlot(0));
             *  EntityManager.SetComponentData(actionEntity, new StActionDualSwitch(rocketEntity, rocketEntity));
             *
             *  EntityManager.GetBuffer<StActionContainer>(entity).Add(new StActionContainer(actionEntity));
             * }
             * // Add grenade
             * {
             *  var actionEntity = EntityManager.CreateEntity
             *  (
             *      typeof(StActionTag),
             *      typeof(StActionOwner),
             *      typeof(StActionSlot),
             *      typeof(StActionAmmo),
             *      typeof(StActionAmmoCooldown),
             *      typeof(StDefActionThrowGrenade)
             *  );
             *
             *  var actionType = typeof(StDefActionThrowGrenade);
             *
             *  EntityManager.SetComponentData(actionEntity, new StActionTag(TypeManager.GetTypeIndex(actionType)));
             *  EntityManager.SetComponentData(actionEntity, new StActionOwner(entity));
             *  EntityManager.SetComponentData(actionEntity, new StActionSlot(1));
             *  EntityManager.SetComponentData(actionEntity, new StActionAmmo(0, 1, 0));
             *  EntityManager.SetComponentData(actionEntity, new StActionAmmoCooldown(-1, 8));
             *  EntityManager.SetComponentData(actionEntity, new StDefActionThrowGrenade(28f, 25, 2));
             *
             *  EntityManager.GetBuffer<StActionContainer>(entity).Add(new StActionContainer(actionEntity));
             * }*/

            // Add transforms component
            EntityManager.AddComponentData(entity, new Position());
            EntityManager.AddComponentData(entity, new Rotation());
            EntityManager.AddComponentData(entity, new StVelocity());

            ShareManager.SetShareOption(entity, typeof(Position), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(Rotation), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(StVelocity), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);

            // Add settings
            EntityManager.AddComponentData(entity, new EntityPhysicLayer(30));
            EntityManager.AddComponentData(entity, new StStamina(4, 0.75f, 0));
            EntityManager.AddComponentData(entity, DefStGroundRunSettings.NewBase());
            EntityManager.AddComponentData(entity, DefStAerialRunSettings.NewBase());
            EntityManager.AddComponentData(entity, DefStJumpSettings.NewBase());
            EntityManager.AddComponentData(entity, DefStDodgeOnGroundSettings.NewBase());
            EntityManager.AddComponentData(entity, new DefStJumpStaminaUsageData()
            {
                Usage = EStaminaUsage.RemoveStamina,
                RemoveBySpeedFactor01 = 0.01f,
                BaseRemove            = 0.1f
            });
            EntityManager.AddComponentData(entity, new DefStDodgeStaminaUsageData()
            {
                Usage      = EStaminaUsage.BlockAction,
                Needed     = 1f,
                BaseRemove = 1f
            });

            ShareManager.SetShareOption(entity, typeof(EntityPhysicLayer), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(StStamina), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStGroundRunSettings), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStAerialRunSettings), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStJumpSettings), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStDodgeOnGroundSettings), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStJumpStaminaUsageData), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStDodgeStaminaUsageData), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);

            // Add simple client inputs
            EntityManager.AddComponentData(entity, new DefStRunClientInput());
            EntityManager.AddComponentData(entity, new DefStJumpClientInput());
            EntityManager.AddComponentData(entity, new DefStDodgeClientInput());
            EntityManager.AddComponentData(entity, new DefStEntityAimClientInput());

            ShareManager.SetShareOption(entity, typeof(DefStRunClientInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStJumpClientInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStDodgeClientInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStEntityAimClientInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);

            // Add global inputs
            EntityManager.AddComponentData(entity, new DefStRunInput());
            EntityManager.AddComponentData(entity, new DefStJumpInput());
            EntityManager.AddComponentData(entity, new DefStDodgeInput());
            EntityManager.AddComponentData(entity, new DefStEntityAimInput());

            ShareManager.SetShareOption(entity, typeof(DefStRunInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStJumpInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStDodgeInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStEntityAimInput), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);

            // Add processable data
            EntityManager.AddComponentData(entity, new DefStJumpProcessData());
            EntityManager.AddComponentData(entity, new DefStDodgeOnGroundProcessData());
            EntityManager.AddComponentData(entity, new DefStWallJumpProcessData());
            EntityManager.AddComponentData(entity, new DefStWallDodgeProcessData());

            ShareManager.SetShareOption(entity, typeof(DefStJumpProcessData), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStDodgeOnGroundProcessData), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(DefStWallDodgeProcessData), ComponentShareOption.Manual, DeliveryMethod.ReliableOrdered);

            // Make the clients able to change the input data
            EntityManager.AddComponentData(entity, new ClientDriveData <DefStRunInput>(Player));
            EntityManager.AddComponentData(entity, new ClientDriveData <DefStJumpInput>(Player));
            EntityManager.AddComponentData(entity, new ClientDriveData <DefStDodgeInput>(Player));
            EntityManager.AddComponentData(entity, new ClientDriveData <DefStEntityAimInput>(Player));

            ShareManager.SetShareOption(entity, typeof(ClientDriveData <DefStRunInput>), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(ClientDriveData <DefStJumpInput>), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(ClientDriveData <DefStDodgeInput>), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
            ShareManager.SetShareOption(entity, typeof(ClientDriveData <DefStEntityAimInput>), ComponentShareOption.Automatic, DeliveryMethod.ReliableOrdered);
        }