protected virtual void CalculateNextRotation(float slowdown, out Quaternion nextRotation) { if (lastDeltaTime > 0.00001f) { Vector2 desiredRotationDirection; if (rvoController != null && rvoController.enabled) { // When using local avoidance, use the actual velocity we are moving with if that velocity // is high enough, otherwise fall back to the velocity that we want to move with (velocity2D). // The local avoidance velocity can be very jittery when the character is close to standing still // as it constantly makes small corrections. We do not want the rotation of the character to be jittery. var actualVelocity = lastDeltaPosition / lastDeltaTime; desiredRotationDirection = Vector2.Lerp(velocity2D, actualVelocity, 4 * actualVelocity.magnitude / (maxSpeed + 0.0001f)); } else { desiredRotationDirection = velocity2D; } // Rotate towards the direction we are moving in. // Don't rotate when we are very close to the target. var currentRotationSpeed = rotationSpeed * Mathf.Max(0, (slowdown - 0.3f) / 0.7f); nextRotation = SimulateRotationTowards(desiredRotationDirection, currentRotationSpeed * lastDeltaTime); } else { // TODO: simulatedRotation nextRotation = rotation; } }
private void UpdatePosition() { if (moveByArc) { if (count < 1.0f && movingToPoint) { count += moveSpeed * Time.deltaTime; Vector3 m1 = Vector2.Lerp(startPosition, middlePoint, count); Vector3 m2 = Vector2.Lerp(middlePoint, targetPosition, count); transform.position = Vector2.Lerp(m1, m2, count); var rotation = Vector2Utils.CalculateFacingToTarget(m1, m2).angle; transform.rotation = rotation; } } else { if (transform.position != new Vector3(targetPosition.x, targetPosition.y, 0) && movingToPoint) { transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * moveSpeed); } else { movingToPoint = true; } } }
private void Start() { birthTime = TimeManager.SongPosition; pathChoices = new PathFunction[] { (speed, intensity, offset) => { }, (speed, intensity, offset) => { transform.position = startPosition + (TimeManager.SongPosition - birthTime) * speed * (Vector2)transform.right; transform.rotation = startRotation; // transform.rotation = startRotation * Quaternion.Euler(0f, 0f, (TimeManager.SongPosition - birthTime) * 5); }, (speed, intensity, offset) => { transform.position = startPosition + (TimeManager.SongPosition - birthTime) * speed * (Vector2)transform.right + intensity * Mathf.Sin((TimeManager.SongPosition - birthTime) * speed) * (Vector2)transform.up; transform.rotation = startRotation; }, (speed, intensity, offset) => { float t = TimeManager.SongPosition - birthTime; transform.position = startPosition + Mathf.Sin(t) * Mathf.Cos(Mathf.PI * t * speed + offset) * intensity * (Vector2)transform.right + Mathf.Sin(t) * Mathf.Sin(t * speed + offset) * intensity * (Vector2)transform.up; transform.rotation = startRotation; }, (speed, intensity, offset) => { float t = TimeManager.SongPosition - birthTime; transform.position = startPosition + Mathf.Sin(t) * Mathf.Cos(t * speed + offset) * intensity * (Vector2)transform.right + Mathf.Sin(t) * Mathf.Sin(Mathf.PI * t * speed + offset) * intensity * (Vector2)transform.up; transform.rotation = startRotation; }, (speed, intensity, offset) => { float t = TimeManager.SongPosition - birthTime; if (t < TimeManager.BeatDuration * 4) { Vector2 center = Vector2.Lerp(new Vector2(10, 10), startPosition, t / (TimeManager.BeatDuration * 4)); transform.position = center + intensity * Mathf.Cos(2 * Mathf.PI * speed * t / (TimeManager.BeatDuration * 4) + offset) * (Vector2)transform.right + intensity * Mathf.Sin(2 * Mathf.PI * speed * t / (TimeManager.BeatDuration * 4) + offset) * (Vector2)transform.up; } else { transform.rotation = Quaternion.Euler(0f, 0f, offset * Mathf.Rad2Deg); transform.position = startPosition + (TimeManager.SongPosition - (birthTime + TimeManager.BeatDuration * 4)) * 3 * speed * (Vector2)transform.right; } }, (speed, intensity, offset) => { float t = TimeManager.SongPosition - birthTime; transform.position = startPosition + Mathf.Sin(t) * Mathf.Cos(t * speed + offset) * intensity * (Vector2)transform.right + Mathf.Sin(t) * Mathf.Sin(t * speed + offset) * intensity * (Vector2)transform.up; } }; }
IEnumerator SmoothMove(Vector2 startPos, Vector2 endPos, float seconds) { float t = 0f; while (t <= 1.0f) { t += Time.deltaTime / seconds; transform.position = Vector2.Lerp(startPos, endPos, Mathf.SmoothStep(0f, 1f, t)); yield return(null); } }
void GenerateObstacleVOs(VOBuffer vos) { var range = maxSpeed * obstacleTimeHorizon; // Iterate through all obstacles that we might need to avoid for (int i = 0; i < simulator.obstacles.Count; i++) { var obstacle = simulator.obstacles[i]; var vertex = obstacle; // Iterate through all edges (defined by vertex and vertex.dir) in the obstacle do { // Ignore the edge if the agent should not collide with it if (vertex.ignore || (vertex.layer & collidesWith) == 0) { vertex = vertex.next; continue; } // Start and end points of the current segment float elevation1, elevation2; var p1 = To2D(vertex.position, out elevation1); var p2 = To2D(vertex.next.position, out elevation2); Vector2 dir = (p2 - p1).normalized; // Signed distance from the line (not segment, lines are infinite) // TODO: Can be optimized float dist = VO.SignedDistanceFromLine(p1, dir, position); if (dist >= -0.01f && dist < range) { float factorAlongSegment = Vector2.Dot(position - p1, p2 - p1) / (p2 - p1).sqrMagnitude; // Calculate the elevation (y) coordinate of the point on the segment closest to the agent var segmentY = Mathf.Lerp(elevation1, elevation2, factorAlongSegment); // Calculate distance from the segment (not line) var sqrDistToSegment = (Vector2.Lerp(p1, p2, factorAlongSegment) - position).sqrMagnitude; // Ignore the segment if it is too far away // or the agent is too high up (or too far down) on the elevation axis (usually y axis) to avoid it. // If the XY plane is used then all elevation checks are disabled if (sqrDistToSegment < range * range && (simulator.movementPlane == MovementPlane.XY || (elevationCoordinate <= segmentY + vertex.height && elevationCoordinate + height >= segmentY))) { vos.Add(VO.SegmentObstacle(p2 - position, p1 - position, Vector2.zero, radius * 0.01f, 1f / ObstacleTimeHorizon, 1f / simulator.DeltaTime)); } } vertex = vertex.next; } while (vertex != obstacle && vertex != null && vertex.next != null); } }
private IEnumerator MoveJob(Vector2 waypoint) { Vector2 start = transform.position; float dist = Vector2.Distance(start, waypoint); float progress = 0; while (Vector2.Distance(waypoint, transform.position) > float.Epsilon) { transform.position = Vector2.Lerp(start, waypoint, progress); yield return(null); progress += MovementSpeed * Time.deltaTime / dist; } }
public void Draw() { var previousColor = Handles.color; Handles.color = _currentColor; if (IsReentrant()) { var points = GetReentrantLinePoints(); Handles.DrawAAPolyLine(Width, points); DrawArrow(Vector2.Lerp(points[2], points[3], 0.5f), points[3] - points[2]); } else { Handles.DrawAAPolyLine(Width, StartPoint, EndPoint); DrawArrow(Vector2.Lerp(StartPoint, EndPoint, 0.5f), EndPoint - StartPoint); } Handles.color = previousColor; }
void Run(Vector2 direction) { if (!canMove) { return; } if (wallGrab) { return; } _animator.SetBool("run", true); if (!wallJumped) { _rigidbody2D.velocity = new Vector2(direction.x * speed, _rigidbody2D.velocity.y); } else { _rigidbody2D.velocity = Vector2.Lerp(_rigidbody2D.velocity, (new Vector2(direction.x * speed, _rigidbody2D.velocity.y)), wallJumpLerp * Time.deltaTime); } }
void TailRender() { float distance = ((Vector2)snakeHead.transform.position - statusesTail[0].pos).magnitude; if (distance > bodyBlockItemDiameter) { Vector2 optimizeDirection = ((Vector2)snakeHead.transform.position - statusesTail[0].pos).normalized; StatusTail statusTail = new StatusTail(); statusTail.pos = statusesTail[0].pos + optimizeDirection * bodyBlockItemDiameter; statusTail.rotation = statusesTail[0].rotation; statusesTail.Insert(0, statusTail); statusesTail.RemoveAt(statusesTail.Count - 1); distance -= bodyBlockItemDiameter; } for (int i = 0; i < tail.Count; i++) { tail[i].transform.position = Vector2.Lerp(statusesTail[i + 1].pos, statusesTail[i].pos, distance / bodyBlockItemDiameter); tail[i].transform.rotation = statusesTail[i + 1].rotation; } }
void FixedUpdate() { ForceHeightLevel(); //Must be the local player, or they cannot move if (!isLocalPlayer) { return; } //Ignore movement controls when typing in chat if (chatRegister.ChatWindow != null && chatRegister.ChatWindow.PlayerIsTyping()) { currentMovement.Set(0, 0); return; } if (Input.GetButtonDown("Toggle Run")) { isWalking = !isWalking; } // TODO: Implement gravity and grabbing // Calculate next movement // The vector is not normalized to allow for the input having potential rise and fall times float x = Input.GetAxisRaw("Horizontal"); float y = Input.GetAxisRaw("Vertical"); // Smoothly transition to next intended movement intendedMovement = new Vector2(x, y).normalized *(isWalking ? walkSpeed : runSpeed); currentMovement = Vector2.Lerp(currentMovement, intendedMovement, Time.deltaTime * (Mathf.Pow(ACCELERATION / 9.5f, 3) / 6)); // Move (without gravity). Whenever we move we also readjust the player's direction to the direction they are running in. characterController.Move(absoluteMovement * Time.deltaTime); // Move the player if (currentMovement != Vector2.zero) { // Determine the absolute movement by aligning input to the camera's looking direction Vector3 absoluteMovement = currentMovement.y * Vector3.Cross(mainCamera.transform.right, Vector3.up).normalized + currentMovement.x * Vector3.Cross(Vector3.up, mainCamera.transform.forward).normalized; if (intendedMovement != Vector2.zero) { //absoluteMovement = Vector3.Lerp(absoluteMovement, newAbsoluteMovement, Time.deltaTime * 2); // Move (without gravity). Whenever we move we also readjust the player's direction to the direction they are running in. characterController.Move(absoluteMovement * Time.deltaTime); // avoid unwanted rotation when you rotate the camera but isn't doing movement input, comment the "if" to see it // Rotate the chest and head IKs objects Quaternion newChestIKRotation = Quaternion.Lerp(chestIK.rotation, Quaternion.LookRotation(absoluteMovement), Time.deltaTime * (isWalking ? 3 : 10)); Quaternion newHeadIKRotation = Quaternion.Lerp(headIK.rotation, Quaternion.LookRotation(absoluteMovement), Time.deltaTime * (isWalking ? 15 : 5)); //float rotationDiference = Quaternion. transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(absoluteMovement), Time.deltaTime * (isWalking ? 5 : 7)); //Mathf.Pow(intendedMovement.magnitude, 2) chestIK.rotation = newChestIKRotation; headIK.rotation = newHeadIKRotation; } if (intendedMovement == Vector2.zero) { Quaternion newChestIKRotation = Quaternion.Lerp(chestIK.rotation, transform.rotation, Time.deltaTime * 3); Quaternion newHeadIKRotation = Quaternion.Lerp(headIK.rotation, transform.rotation, Time.deltaTime * 8); absoluteMovement = Vector3.Lerp(absoluteMovement, Vector3.zero, Time.deltaTime * 5); characterController.Move(absoluteMovement * Time.deltaTime); chestIK.rotation = newChestIKRotation; headIK.rotation = newHeadIKRotation; } } }
void GenerateNeighbourAgentVOs(VOBuffer vos) { float inverseAgentTimeHorizon = 1.0f / agentTimeHorizon; // The RVO algorithm assumes we will continue to // move in roughly the same direction Vector2 optimalVelocity = currentVelocity; for (int o = 0; o < neighbours.Count; o++) { Agent other = neighbours[o]; // Don't avoid ourselves if (other == this) { continue; } // Interval along the y axis in which the agents overlap float maxY = System.Math.Min(elevationCoordinate + height, other.elevationCoordinate + other.height); float minY = System.Math.Max(elevationCoordinate, other.elevationCoordinate); // The agents cannot collide since they are on different y-levels if (maxY - minY < 0) { continue; } float totalRadius = radius + other.radius; // Describes a circle on the border of the VO Vector2 voBoundingOrigin = other.position - position; float avoidanceStrength; if (other.locked || other.manuallyControlled) { avoidanceStrength = 1; } else if (other.Priority > 0.00001f || Priority > 0.00001f) { avoidanceStrength = other.Priority / (Priority + other.Priority); } else { // Both this agent's priority and the other agent's priority is zero or negative // Assume they have the same priority avoidanceStrength = 0.5f; } // We assume that the other agent will continue to move with roughly the same velocity if the priorities for the agents are similar. // If the other agent has a higher priority than this agent (avoidanceStrength > 0.5) then we will assume it will move more along its // desired velocity. This will have the effect of other agents trying to clear a path for where a high priority agent wants to go. // If this is not done then even high priority agents can get stuck when it is really crowded and they have had to slow down. Vector2 otherOptimalVelocity = Vector2.Lerp(other.currentVelocity, other.desiredVelocity, 2 * avoidanceStrength - 1); var voCenter = Vector2.Lerp(optimalVelocity, otherOptimalVelocity, avoidanceStrength); vos.Add(new VO(voBoundingOrigin, voCenter, totalRadius, inverseAgentTimeHorizon, 1 / simulator.DeltaTime)); if (DebugDraw) { DrawVO(position + voBoundingOrigin * inverseAgentTimeHorizon + voCenter, totalRadius * inverseAgentTimeHorizon, position + voCenter); } } }
IEnumerator Moving(Vector2 target, float speed, bool smooth) { targetPosition = target; //now we want to get the padding for our character Vector2 padding = anchorPadding; //now get the limitations for 0 to 100% movement. The farthest a character can move to the right before 100% should be the 1 value float maxX = 1f - padding.x; float maxY = 1f - padding.y; //now get the actal position target for the minimum anchors(left/bottom bounds) fo the character. because maxX and maxY is just a percentage. Vector2 minAnchorTarget = new Vector2(maxX * targetPosition.x, maxY * targetPosition.y); //move until we reach end of frame speed *= Time.deltaTime; while (root.anchorMin != minAnchorTarget) { root.anchorMin = (!smooth) ? Vector2.MoveTowards(root.anchorMin, minAnchorTarget, speed) : Vector2.Lerp(root.anchorMin, minAnchorTarget, speed); root.anchorMax = root.anchorMin + padding; yield return(new WaitForEndOfFrame()); } StopMoving(); }