private bool ProcessItem
        (
            ref Entity entity,
            ref StVelocity velocity,
            ref DefStJumpSettings setting,
            ref DefStRunInput runInput,
            ref DefStJumpInput input,
            ref DefStWallJumpProcessData process,
            ref CharacterControllerState state,
            Transform transform
        )
        {
            var action = input.State == InputState.Down && !MvUtils.OnGround(state, velocity) && Time.time > process.TimeBeforeNextWJ;

            if (!action)
            {
                return(false);
            }

            var originalVelocity = velocity.Value;
            var fwd       = transform.forward;
            var pos       = transform.position + new Vector3(0, 0.4f + 0.1f); // hardcoded value (stepoffset)
            var rot       = transform.rotation;
            var rd        = 0.3f + 0.075f;                                    // (radius)
            var sw        = 0.07f + 0.025f;                                   // hardcoded value (skinwidth)
            var height    = 2f - 0.4f;                                        // harcoded value (height and stepOffset)
            var subheight = (height * 0.75f) - 0.005f;

            CPhysicSettings.Active.SetGlobalCollision(transform.gameObject, false);

            var direction = (Vector3)SrtComputeDirection(fwd, rot, runInput.Direction);
            var rayTrace  = UtilityWallRayTrace.RayTrace(ref direction, ref pos, ref rd, ref sw, ref height, ref subheight, transform.GetComponent <Collider>());

            Debug.DrawRay(rayTrace.point, rayTrace.normal, Color.red, 10);

            CPhysicSettings.Active.SetGlobalCollision(transform.gameObject, true);

            var success = rayTrace.normal != Vector3.zero && Mathf.Abs(rayTrace.normal.y) < 0.2f;

            if (success)
            {
                rayTrace.normal = rayTrace.normal.ToGrid(1).normalized;

                velocity.Value = RaycastUtilities.SlideVelocityNoYChange(velocity.Value, rayTrace.normal);

                velocity.Value.y = math.max(math.min(velocity.Value.y + 6.5f, 12f), 0);

                var previousVelocity = velocity.Value;
                var bounceDir        = rayTrace.normal * 6f;
                var minSpeed         = bounceDir.magnitude;

                velocity.Value += bounceDir;

                var flatVelocity = velocity.Value.ToGrid(1);
                var oldY         = velocity.Value.y;

                velocity.Value = Vector3.ClampMagnitude(flatVelocity, Mathf.Max(previousVelocity.magnitude, minSpeed));

                velocity.Value.y = oldY;

                process.TimeBeforeNextWJ = Time.time + DefaultCooldown;

                input.TimeBeforeResetState = -1f;
                input.State = InputState.None;

                BroadcastNewEntity(PostUpdateCommands, true);
                PostUpdateCommands.AddComponent(new DefStWallJumpEvent(Time.time, Time.frameCount, entity, originalVelocity, rayTrace.normal));

                MvDelegateEvents.InvokeCharacterWalljump(entity);
            }

            return(success);
        }
        private void SimulatePhysicStep(float dt)
        {
            for (int i = 0; i != m_Group.Length; i++)
            {
                var oldVelocity = m_Group.VelocityArray[i].Value;
                var motor       = m_Group.MotorArray[i];
                var gameObject  = m_Group.GameObjects[i];
                var transform   = m_Group.Transforms[i];
                var slopeLimit  = motor.CharacterController.slopeLimit;
                var entity      = m_Group.Entities[i];

                var layerMask         = CPhysicSettings.PhysicInteractionLayerMask;
                var wasGrounded       = motor.IsGrounded(layerMask);
                var wasStableOnGround = motor.IsStableOnGround;
                var wasSliding        = motor.IsSliding;
                if (!wasGrounded && !wasStableOnGround && !wasSliding)
                {
                    oldVelocity += new Vector3(0, Physics.gravity.y, 0) * dt;
                    motor.CharacterController.stepOffset = 0.5f;
                }
                else if (wasGrounded && wasStableOnGround && !wasSliding)
                {
                    motor.CharacterController.stepOffset = 0.5f;

                    //if (oldVelocity.y <= 0) oldVelocity.y = -motor.CharacterController.stepOffset;
                    if (oldVelocity.y <= 0)
                    {
                        oldVelocity.y = -1;
                    }
                }
                else
                {
                    oldVelocity.y = -1;
                }

                if (!wasGrounded && Input.GetKey(KeyCode.LeftControl) && oldVelocity.y < -2f)
                {
                    oldVelocity.y = Mathf.Lerp(oldVelocity.y, -0.25f, dt * 4f);
                }

                var oldPos   = transform.position;
                var velocity = oldVelocity * dt;

                CPhysicSettings.Active.SetGlobalCollision(gameObject, true);
                var previousPosition = transform.position;
                var ev = motor.MoveBy(velocity);
                CPhysicSettings.Active.SetGlobalCollision(gameObject, false);

                var isGrounded      = motor.IsGrounded(layerMask);
                var correctVelocity = oldVelocity;

                for (var j = ev.EventsStartIndex; j < ev.EventsLength; j++)
                {
                    var hitEvent = ev.GetColliderHit(j);
                    if (OnControllerHasHitACollider(hitEvent, velocity.magnitude, oldPos, motor, transform,
                                                    ref correctVelocity))
                    {
                        break;
                    }
                }

                var newPosition      = transform.position;
                var momentum         = (newPosition - previousPosition) / dt;
                var previousMomentum = motor.Momentum;

                // This is wrong, it should be done when sliding.
                // In real life, we don't keep the height momentum when running.

                /*if (wasGrounded && !isGrounded && previousMomentum.y > 0.5f && correctVelocity.y <= 0.1f)
                 * {
                 *  isM = true;
                 *
                 *  correctVelocity.y += previousMomentum.y;
                 *
                 *  motor.MoveBy(Vector3.up * (previousMomentum.y * dt));
                 * }*/

                // Slide on floor (done next frame)
                Profiler.BeginSample("Slide on floor");
                Profiler.BeginSample("Get angle");
                var slideAngle = Vector3.Angle(motor.AngleDir, Vector3.up);
                Debug.DrawRay(motor.transform.position, motor.AngleDir, Color.red, 5);
                Profiler.EndSample();
                if (slideAngle > motor.CharacterController.slopeLimit && slideAngle < 80 && isGrounded)
                {
                    Debug.Log("Sliding");
                    var oldY = correctVelocity.y;

                    var undesiredMotion = motor.AngleDir * Vector3.Dot(correctVelocity, motor.AngleDir);
                    var desiredMotion   = correctVelocity - undesiredMotion;
                    var leftOverInertia = desiredMotion * 0.5f * dt;

                    correctVelocity = desiredMotion + leftOverInertia;

                    /*var velocityToChoose = correctVelocity;
                     * if (Math.Abs(velocityToChoose.y) < 0.001)
                     *  velocityToChoose.y = -1f;*/

                    //correctVelocity = RaycastUtilities.SlideVelocity(velocityToChoose, motor.AngleDir);
                    //correctVelocity.y = oldY;
                    correctVelocity += RaycastUtilities.SlideVelocity(new Vector3(0, Physics.gravity.y, 0) * dt * (slideAngle / 90), motor.AngleDir);

                    Debug.Log((slideAngle / 90));
                    //correctVelocity.y = oldY * dt;
                    //correctVelocity.y = Mathf.Clamp(correctVelocity.y, -10, 60);

                    motor.AngleDir = ProbeGround(motor, transform, motor.AngleDir, 90, 90);

                    motor.IsStableOnGround = false;
                    motor.IsSliding        = true;
                    //motor.CharacterController.stepOffset = 0f;
                }
                else
                {
                    Profiler.BeginSample("Set properties");
                    motor.IsStableOnGround = isGrounded;
                    motor.IsSliding        = false;
                    Profiler.EndSample();
                }
                Profiler.EndSample();

                Profiler.BeginSample("Set AngleDir");
                if (isGrounded)
                {
                    motor.AngleDir    = GetAngleDir(motor, transform);
                    correctVelocity.y = Mathf.Max(correctVelocity.y, 0);
                }
                else if (wasGrounded && !isGrounded && correctVelocity.y < 0.001f)
                {
                    motor.AngleDir = ProbeGround(motor, transform, motor.AngleDir,
                                                 slopeLimit - Mathf.Clamp(correctVelocity.ToGrid(1).magnitude, 0, 15) * 3 + 15, slopeLimit);
                }
                Profiler.EndSample();

                motor.Momentum = momentum;

                var events = motor.AllColliderHitsInFrame;
                for (int x = 0; x != events.Count; x++)
                {
                    var hitEvent = events[x];
                    // TODO Fire events
                }

                if (motor.IsGrounded(layerMask) && !wasGrounded)
                {
                    MvDelegateEvents.InvokeCharacterLand(entity);
                }

                m_Group.States[i]        = new CharacterControllerState(motor.IsGrounded(layerMask), motor.IsStableOnGround, motor.IsSliding, motor.AngleDir);
                m_Group.VelocityArray[i] = new StVelocity(correctVelocity);
            }
        }
示例#3
0
        private bool ProcessItem
        (
            ref Entity entity,
            ref StVelocity velocity,
            ref DefStRunInput runInput,
            ref DefStDodgeOnGroundSettings setting,
            ref DefStDodgeInput input,
            ref DefStDodgeOnGroundProcessData process,
            ref CharacterControllerState state,
            Transform transform
        )
        {
            var doDodge = input.State != InputState.None && process.CooldownBeforeNextDodge <= 0f && MvUtils.OnGround(state, velocity);

            if (input.TimeBeforeResetState <= 0f)
            {
                input.State = InputState.None;
            }

            // We expect the developpers to check for staminas or things like that for this command.
            EntityManager.SetComponentData(m_CmdDoDodge, new EntityCommandTarget(entity));
            DiffuseCommand(m_CmdDoDodge, m_CmdDoDodgeResult, doDodge, CmdState.Begin);

            doDodge = GetCmdResult(m_CmdDoDodgeResult);
            if (!doDodge)
            {
                return(false);
            }

            process.StartFlatSpeed = velocity.Value.ToGrid(1).magnitude;

            var direction = SrtComputeDirection(transform.forward.normalized, transform.rotation, runInput.Direction);

            velocity.Value.y = 0f;

            var addVelocity = SrtDodge(velocity.Value, direction, setting.AdditiveSpeed, setting.MinSpeed, setting.MaxSpeed);
            var momentum    = transform.GetComponent <CharacterControllerMotor>().Momentum;

            if (Vector3.Dot(velocity.Value.normalized, math.normalizesafe(addVelocity)) >= 0.9f)
            {
                addVelocity = (momentum.normalized + ((Vector3)addVelocity).normalized).normalized * math.length(addVelocity);
                Debug.Log(addVelocity);
            }

            velocity.Value  = addVelocity;
            velocity.Value += Vector3.up * setting.VerticalPower;

            input.TimeBeforeResetState = -1f;
            input.State = InputState.None;

            process.CooldownBeforeNextDodge = 0.5f;
            process.InertieDelta            = 0.1f;
            process.Direction = direction;
            process.IsDodging = 1;
            process.StartAfterDodgeFlatSpeed = velocity.Value.ToGrid(1).magnitude;

            // We except developpers to just clean the pre-command phase, and not applying things like reducing stamina...
            DiffuseCommand(m_CmdDoDodge, m_CmdDoDodgeResult, true, CmdState.End);

            // Send dodge message to clients
            BroadcastNewEntity(PostUpdateCommands, true);
            PostUpdateCommands.AddComponent(new DefStDodgeEvent(Time.time, Time.frameCount, entity));

            MvDelegateEvents.InvokeCharacterDodge(entity);

            return(true);
        }
示例#4
0
        private bool ProcessItem
        (
            ref Entity entity,
            ref StVelocity velocity,
            ref DefStJumpSettings setting,
            ref DefStRunInput runInput,
            ref DefStJumpInput input,
            ref DefStJumpProcessData process,
            ref CharacterControllerState state,
            Transform transform
        )
        {
            if (MvUtils.OnGround(state, velocity))
            {
                process.ComboCtx = 0;
            }

            if (input.ContinueJump == 0)
            {
                process.NeedToChain = 0;
            }

            var inputCanJump = input.State == InputState.Down || (input.ContinueJump == 1 && process.NeedToChain == 1);
            var doJump       = inputCanJump && (process.ComboCtx < setting.MaxCombo && process.CooldownBeforeNextJump <= 0f) &&
                               (MvUtils.OnGround(state, velocity) || process.ComboCtx > 0);
            var airJump = doJump && !state.IsGrounded() && !state.IsSliding();

            if (input.TimeBeforeResetState <= 0f)
            {
                input.State = InputState.None;
            }

            process.CooldownBeforeNextJump -= Time.deltaTime;
            input.TimeBeforeResetState     -= Time.deltaTime;

            // We expect the developpers to check for staminas or things like that for this command.
            DiffuseCommand(m_CmdDoJump, m_CmdDoJumpResult, doJump, CmdState.Begin);

            doJump = GetCmdResult(m_CmdDoJumpResult);
            if (!doJump)
            {
                return(false);
            }

            var direction   = SrtComputeDirection(transform.forward, transform.rotation, runInput.Direction);
            var strafeAngle = SrtGetStrafeAngleNormalized(direction, velocity.Value);

            if (math.all(runInput.Direction == float2.zero))
            {
                strafeAngle *= 0.5f;
            }

            if (input.State == InputState.Down)
            {
                process.NeedToChain = 1;
            }

            velocity.Value.y = math.max(velocity.Value.y, 0);
            if (!airJump)
            {
                var motor = transform.GetComponent <CharacterControllerMotor>();

                velocity.Value += Vector3.up * (setting.JumpPower * (input.State != InputState.Down ? 0.75f : 1f));
                //if (motor.Momentum.y > 0) velocity.Value += Vector3.up * (motor.Momentum.normalized.y * 6f);
            }
            else
            {
                velocity.Value = Vector3.up * setting.JumpPower;
            }

            if (airJump)
            {
                velocity.Value = math.lerp(velocity.Value, SrtAirDash(velocity.Value, direction), 1f);
            }
            else if (input.State != InputState.Down)
            {
                velocity.Value += (Vector3)(direction * (strafeAngle * 5f));

                var oldY      = velocity.Value.y;
                var currSpeed = velocity.Value.ToGrid(1).magnitude;
                var newSpeed  = math.min(currSpeed + strafeAngle * 2f, math.max(currSpeed, 18f));
                velocity.Value   = velocity.Value.ToGrid(1).normalized *newSpeed;
                velocity.Value.y = oldY;
            }
            else
            {
                var oldY = velocity.Value.y;
                //velocity.Value = velocity.Value.ToGrid(1).normalized * (velocity.Value.ToGrid(1).magnitude - 2.5f);
                velocity.Value.y = oldY;
            }

            input.TimeBeforeResetState = -1f;
            input.State = InputState.Pressed;

            process.ComboCtx++;
            process.CooldownBeforeNextJump = 0.1f;

            // We except developpers to just clean the pre-command phase, and not applying things like reducing stamina...
            DiffuseCommand(m_CmdDoJump, m_CmdDoJumpResult, true, CmdState.End);

            // Send event to clients
            BroadcastNewEntity(PostUpdateCommands, true);
            PostUpdateCommands.AddComponent(new DefStJumpEvent(Time.time, Time.frameCount, entity));

            MvDelegateEvents.InvokeCharacterJump(entity);

            return(true);
        }