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); } }
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); }
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); }