public override void RotateToAlignWithNormal(Vector3 a_Normal, RotateMethod a_Method = RotateMethod.FromBottom) { if (m_CapsuleTransform.CanRotate(a_Normal, a_Method)) { m_CapsuleTransform.Rotate(a_Normal, a_Method); UpdateContextInfo(); } }
public void ApplyEntireMovement(CapsuleTransform a_Transform) { if (a_Transform.GetPosition() != m_Position) { a_Transform.SetPosition(m_Position); } if (a_Transform.GetUpDirection() != m_UpDirection) { a_Transform.Rotate(m_UpDirection, m_RotateMethod); } if (a_Transform.GetLength() != m_Length) { a_Transform.SetLength(m_Length, m_ResizeMethod); } }
protected override void GeneratePath() { CEdgeCastInfo info = m_ControlledCollider.GetEdgeCastInfo(); m_Path.Clear(); CapsuleTransform copy = m_ControlledCollider.GetCapsuleTransformCopy(); //First node is in edgehang alignment, moving away from the edge mildly CapsuleMovementPathNode newNode = m_Path.CreateFirstNode(copy); Vector3 upCenter = info.GetProposedHeadPoint(); upCenter += m_ControlledCollider.GetEdgeCastInfo().GetWallNormal() * 0.03f; copy.SetUpCenter(upCenter); copy.Rotate(info.GetUpDirection(), RotateMethod.FromTop); newNode = m_Path.DuplicateAndAddLastNode(); newNode.CopyFromTransform(copy); //Second node moves up along local up, until the bottom can slide over the edge newNode = m_Path.DuplicateAndAddLastNode(); newNode.m_Duration = m_MoveUpTime; float contactDot = Vector3.Dot(info.GetEdgeNormal(), info.GetEdgePoint()); float bottomDot = Vector3.Dot(info.GetEdgeNormal(), copy.GetDownCenter()) - m_ControlledCollider.GetRadius() - m_MoveUpMargin; float normalDot = Vector3.Dot(info.GetEdgeNormal(), copy.GetUpDirection()); float rawDistance = contactDot - bottomDot; float distance = rawDistance / normalDot; newNode.m_Position += copy.GetUpDirection() * distance; newNode.ApplyEntireMovement(copy); //Third node snaps the capsule to the "upright" position for the ground it's going to stand on newNode = m_Path.DuplicateAndAddLastNode(); newNode.m_Duration = 0.0f; newNode.m_UpDirection = (m_CharacterController.GetAlignsToGround()) ? info.GetEdgeNormal() : Vector3.up; newNode.m_RotateMethod = RotateMethod.FromBottom; newNode.ApplyEntireMovement(copy); newNode.m_Position = copy.GetPosition(); //Final node moves the capsule over the ground newNode = m_Path.DuplicateAndAddLastNode(); newNode.m_Duration = m_MoveSideTime; Vector3 direction = CState.GetDirectionAlongNormal(-info.GetWallNormal(), info.GetEdgeNormal()); newNode.m_Position += direction * m_MoveSideDistance; newNode.ApplyEntireMovement(copy); }
//Called for every fixedupdate that this module is active public override void FixedUpdateModule() { float currentTransitionTime = Time.time - m_TransitionStartTime; //A MovingColPoint is used to move and rotate the animation path when the collider it starts on is moved //This allows animated abilities to work on moving colliders if (m_ReferencePoint != null) { //Position CapsuleTransform copy = m_ControlledCollider.GetCapsuleTransformCopy(); Vector3 diff = m_ReferencePoint.m_Transform.position - m_ReferencePoint.m_PrevPoint; copy.Move(diff); m_Path.Move(diff); //Rotation Quaternion rotationDifference = Quaternion.FromToRotation(m_ReferencePoint.m_PrevRot * Vector3.up, m_ReferencePoint.m_Transform.rotation * Vector3.up); copy.Rotate(rotationDifference * copy.GetUpDirection(), RotateMethod.FromCenter); m_Path.Rotate(rotationDifference, m_ReferencePoint.m_PrevPoint); //Offset for rotation Vector3 newRelativePoint = rotationDifference * m_ReferencePoint.m_PointRelativeToThis; Vector3 relativeDifference = newRelativePoint - m_ReferencePoint.m_PointRelativeToThis; copy.Move(relativeDifference); m_ReferencePoint.m_PrevPoint = m_ReferencePoint.m_Transform.position; m_ReferencePoint.m_PrevRot = m_ReferencePoint.m_Transform.rotation; m_ReferencePoint.m_PointRelativeToThis = m_ReferencePoint.m_Transform.position - m_ControlledCollider.GetCapsuleTransform().GetPosition(); m_ReferencePoint.m_Normal = Quaternion.FromToRotation(m_ReferencePoint.m_PrevRot * Vector3.up, m_ReferencePoint.m_Transform.rotation * Vector3.up) * m_ReferencePoint.m_Normal; if (copy.CanExistHere()) { m_ControlledCollider.ApplyCapsuleTransform(copy); } else { m_WasInterrupted = true; return; } } m_ControlledCollider.SetVelocity(Vector2.zero); //Move along the nodes as long as they can be applied (either they are finished or their duration is 0) while (!m_Path.IsDone() && m_Path.m_CurrentPathNode != null && (m_Path.m_CurrentPathNode.m_Duration == 0 || Time.time - m_TransitionStartTime >= m_Path.m_CurrentPathNode.m_Duration)) { if (m_Path.m_CurrentPathNode.CanApplyEntireMovement(m_ControlledCollider.GetCapsuleTransform())) { m_TransitionStartTime += m_Path.m_CurrentPathNode.m_Duration; currentTransitionTime -= m_Path.m_CurrentPathNode.m_Duration; m_Path.m_CurrentPathNode.ApplyEntireMovement(m_ControlledCollider.GetCapsuleTransform()); m_Path.IncrementCurrentNode(); } else { m_WasInterrupted = true; return; } } //Move along the current node if (m_Path.CanApplyMotion(m_ControlledCollider.GetCapsuleTransform(), currentTransitionTime)) { m_Path.ApplyMotion(m_ControlledCollider.GetCapsuleTransform(), currentTransitionTime); } else { m_WasInterrupted = true; return; } m_ControlledCollider.UpdateContextInfo(); }