protected override Vector3 GetShootDirection() { var camera = Camera.main; var shootingOrigin = Refs.shootingOrigin.position; var direction = shootingOrigin - camera.transform.position; direction = Vector3.Project(direction, camera.transform.forward); var mousePosition = Input.mousePosition; mousePosition.z = direction.magnitude; var mousePos = camera.ScreenToWorldPoint(mousePosition); direction = mousePos - shootingOrigin; direction = Vector3.ProjectOnPlane(direction, Vector3.up).normalized; return(direction); }
void FixedUpdate() { Vector3 pos = transform.position; float module = (m_heavy_body_pos - pos).magnitude; if (module > 1000) { Destroy(transform.gameObject); } if (module < 1) { m_v -= 2 * m_v.Project(m_heavy_body_pos - pos); } float denom = module * module * module; Vector3 a = m_G * m_M / denom * (m_heavy_body_pos - pos); float dt = Time.deltaTime; transform.Translate(dt * (m_v + a * dt / 2)); m_v += a * dt; }
private void CalculateFriction() { var isGrounded = _wheelCollisionDetector.TryGetCollision(out var point, out var normal, out var collider, out var rb, out var t); if (!isGrounded) { return; } var forceOffset = transform.up * _applyForcesOffset; var right = transform.right; var forward = transform.forward; var direction = Vector3.Cross(normal, right); if (motorTorque < 0) { direction *= -1; } var lateralVelocity = Vector3.Project(velocity, right); var forwardVelocity = Vector3.Project(velocity, forward); var slip = (forwardVelocity + lateralVelocity) / 2; var lateralFriction = Vector3.Project(right, slip).magnitude *lateralVelocity.magnitude *lateralFrictionMultiplier / Time.fixedDeltaTime; _rb.AddForceAtPosition(-Vector3.Project(slip, lateralVelocity).normalized *lateralFriction, point + forceOffset); var motorForce = Mathf.Abs(motorTorque / _wheel.GetRadius()); var maxForwardFriction = motorForce * forwardFrictionCoeff; var appliedForwardFriction = Mathf.Clamp(motorForce, 0, maxForwardFriction); var forwardForce = direction.normalized * appliedForwardFriction * engineShaftToWheelRatio; _rb.AddForceAtPosition(forwardForce, point + forceOffset); }
/// <summary> /// Calculate the distance between two point's projections on a plane. /// </summary> /// <param name="v"></param> /// <param name="u"></param> /// <param name="planePos">An arbitrary point inside the plane.</param> /// <param name="planeRot">The plane's rotation.</param> /// <returns>The distance of both points' projection in the plane.</returns> public static float distance(this Vector3 v, Vector3 u, Vector3 planePos, Quaternion planeRot) { var localv = v.Project( planePos, planeRot ); var localu = u.Project( planePos, planeRot ); return localv.distance( localu ); }
/// <summary> /// Calculate the squared distance between two points' projections on an arbitrary plane. /// </summary> /// <param name="v"></param> /// <param name="normal">Normal defining the plane to project on.</param> /// <returns>The squared distance between the two points on the plane.</returns> public static float sqrDistance(this Vector3 v, Vector3 u, Vector3 normal) { var localv = v.Project( normal ); var localu = u.Project( normal ); return localv.distance( localu ); }
public static Vector3 ProjectOnPlane(Vector3 vector, Vector3 planeNormal) { return(vector - Vector3.Project(vector, planeNormal)); }
public static Vector3 Exclude(Vector3 excludeThis, Vector3 fromThat) { return(fromThat - Vector3.Project(fromThat, excludeThis)); }
public static Vector3 Project(this Vector3 u, Vector3 v) { return(Vector3.Project(u, v)); }
/// <summary> /// Returns the angle which points towards the provided mouse point /// </summary> /// <param name="mousePoint">the point to aim at</param> /// <returns>angle that points towars mousepoint</returns> public Vector3 GetAngle(Vector3 mousePoint) { Vector3 v_RP_MP = mousePoint - RotationPoint.transform.position; Vector3 norm_GP_prj_RPMP = Vector3.Project(v_RP_MP, FirePoint.transform.right); Vector3 CheckV2 = RotationPoint.position + norm_GP_prj_RPMP - new Vector3(mousePoint.x, mousePoint.y); Vector2 newCheckV = RotationPoint.transform.position - FirePoint.transform.position; if (Mathf.Floor(CheckV.magnitude * 10) != Mathf.Floor(newCheckV.magnitude * 10)) { this.CheckV = newCheckV; CreateHelperObjects(); } if (CheckV2.magnitude > 0.35) { CreateHelperObjects(); } // rotates the helper gun point towards the mouse v_RP_MP = mousePoint - RotationPoint.transform.position; float z_angle = this.RadianToDegree(Math.Atan2(v_RP_MP.y, v_RP_MP.x)); bool isFlipped = (z_angle <90 && z_angle> -90) ? false : true; Vector3 angle = (isFlipped) ? new Vector3(180, 0, -z_angle) : new Vector3(0, 0, z_angle); helperRotPoint.transform.rotation = Quaternion.Euler(angle); // finds the vector projected from the shooting direction on the vector from the helper GP to the MP Vector3 v_GP_MP = mousePoint - helperAimPoint.transform.position; Vector3 norm_GP = helperAimPoint.transform.right; Vector3 norm_GP_Prj_GPMP = Vector3.Project(v_GP_MP, norm_GP); // finds the point where a line from the helper GP to the point found in the block above // wold intersect a circle centered at the RP with a radius of the distance between the RP and MP Vector3 v_RP_GP = helperAimPoint.transform.position - helperRotPoint.transform.position; Vector3 V2 = (norm_GP_Prj_GPMP + v_RP_GP); float r = new Vector2(v_RP_MP.x, v_RP_MP.y).magnitude; float x1 = v_RP_GP.x; float y1 = v_RP_GP.y; float x2 = V2.x; float y2 = V2.y; float dx = x2 - x1; float dy = y2 - y1; float dr = Mathf.Sqrt(Mathf.Pow(dx, 2) + Mathf.Pow(dy, 2)); float D = x1 * y2 - x2 * y1; float xCord = 0; float yCord = 0; float toSqr = Mathf.Pow(r, 2) * Mathf.Pow(dr, 2) - Mathf.Pow(D, 2); // to avoid sqrt(-num) only use the "correct" coordinates for x,y when the squared block is // bigger then 0 if (toSqr > 0) { float sgnX = (dy < 0) ? -1 : 1; float xCord1 = (D * dy + sgnX * dx * Mathf.Sqrt(toSqr)) / Mathf.Pow(dr, 2); float xCord2 = (D * dy - sgnX * dx * Mathf.Sqrt(toSqr)) / Mathf.Pow(dr, 2); float yCord1 = (-D * dx + Mathf.Abs(dy) * Mathf.Sqrt(toSqr)) / Mathf.Pow(dr, 2); float yCord2 = (-D * dx - Mathf.Abs(dy) * Mathf.Sqrt(toSqr)) / Mathf.Pow(dr, 2); Vector2 helper1 = new Vector2(helperAimPoint.transform.right.x, helperAimPoint.transform.right.y) - new Vector2(xCord1, yCord1); Vector2 helper2 = new Vector2(helperAimPoint.transform.right.x, helperAimPoint.transform.right.y) - new Vector2(xCord2, yCord2); if (debug) { Debug.DrawLine(Vector3.zero, new Vector3(xCord1, yCord1), Color.red); Debug.DrawLine(Vector3.zero, new Vector3(xCord2, yCord2), Color.black); } // if checks which one of the two fond points is closest and uses that one // the other point wold be on the other intersection point for the ray on the circle if (helper1.magnitude > helper2.magnitude) { xCord = xCord2; yCord = yCord2; } else { xCord = xCord1; yCord = yCord1; } float ang2 = this.RadianToDegree(Math.Atan2(yCord, xCord)); float deltaAng = ang2 - z_angle; z_angle -= deltaAng; } else { // use the v2 as the gun angle, technically not correct but it works float ang2 = this.RadianToDegree(Math.Atan2(V2.y, V2.x)); float deltaAng = ang2 - z_angle; z_angle -= deltaAng; } if (debug) { Debug.Log(CheckV2.magnitude); Debug.DrawLine(Vector3.zero, CheckV2, Color.green); Debug.DrawLine(RotationPoint.position, Camera.main.ScreenToWorldPoint(Input.mousePosition), Color.magenta); Debug.DrawRay(Vector3.zero, RotationPoint.position + norm_GP_prj_RPMP, Color.gray); Debug.DrawRay(FirePoint.transform.position, FirePoint.transform.right * 100, Color.cyan); Debug.DrawRay(Vector3.zero, helperAimPoint.transform.right * 100, Color.white); } return((isFlipped) ? new Vector3(180, 0, -z_angle) : new Vector3(0, 0, z_angle)); }
protected override void OnUpdate() { if (startCountdownServerSystem.raceHasStarted) { var tick = ghostPredictionSystemGroup.PredictingTick; Entities.ForEach((Entity carEntity, DynamicBuffer <PlayerInput> inputBuffer, ref SynchronizedCarComponent carComponent, ref HealthComponent healthComponent, ref CarComponent serverCarComponent, ref PhysicsVelocity velocity, ref Rotation rotation) => { PlayerInput input; inputBuffer.GetDataAtTick(tick, out input); bool playerCanControl = healthComponent.Health > 0 && EntityManager.GetComponentData <ProgressionComponent>(carEntity).CrossedCheckpoints < checkpointInitializationSystem.numberOfCheckpoints * GameSession.serverSession.laps; bool keyForwardPressed = Convert.ToBoolean(input.keyForwardPressed) && playerCanControl; bool keyBackwardPressed = Convert.ToBoolean(input.keyBackwardPressed) && playerCanControl; bool keyTurnRightPressed = Convert.ToBoolean(input.keyTurnRightPressed) && playerCanControl; bool keyTurnLeftPressed = Convert.ToBoolean(input.keyTurnLeftPressed) && playerCanControl; if (keyTurnRightPressed && !keyTurnLeftPressed) { if (carComponent.SteerAngle < 0) { carComponent.SteerAngle = 0; } if (carComponent.SteerAngle < SerializedFields.singleton.maxSteerAngle) { carComponent.SteerAngle += SerializedFields.singleton.wheelSteeringAngularSpeed * simulationDeltaTime; if (carComponent.SteerAngle > SerializedFields.singleton.maxSteerAngle) { carComponent.SteerAngle = SerializedFields.singleton.maxSteerAngle; } } } else if (keyTurnLeftPressed && !keyTurnRightPressed) { if (carComponent.SteerAngle > 0) { carComponent.SteerAngle = 0; } if (carComponent.SteerAngle > -SerializedFields.singleton.maxSteerAngle) { carComponent.SteerAngle -= SerializedFields.singleton.wheelSteeringAngularSpeed * simulationDeltaTime; if (carComponent.SteerAngle < -SerializedFields.singleton.maxSteerAngle) { carComponent.SteerAngle = -SerializedFields.singleton.maxSteerAngle; } } } else if (!keyTurnRightPressed && !keyTurnLeftPressed) { if (carComponent.SteerAngle > 0) { carComponent.SteerAngle -= SerializedFields.singleton.idleWheelSteeringAngularSpeed * simulationDeltaTime; if (carComponent.SteerAngle < 0) { carComponent.SteerAngle = 0; } } else if (carComponent.SteerAngle < 0) { carComponent.SteerAngle += SerializedFields.singleton.idleWheelSteeringAngularSpeed * simulationDeltaTime; if (carComponent.SteerAngle > 0) { carComponent.SteerAngle = 0; } } } float turningRadiusInverse = CalculateTurningRadiusInverse(carComponent.SteerAngle); Vector3 localVelocity = math.mul(math.inverse(rotation.Value), velocity.Linear); if (localVelocity.magnitude > 0) { Vector3 resistance = -localVelocity.normalized * localVelocity.sqrMagnitude * SerializedFields.singleton.forwardAcceleration / math.pow(SerializedFields.singleton.maxCarSpeed, 2) * simulationDeltaTime; localVelocity += resistance; } if (localVelocity.x > 0) { localVelocity -= new Vector3(SerializedFields.singleton.friction * 9.81f * simulationDeltaTime, 0, 0); if (localVelocity.x < 0) { localVelocity = new Vector3(0, localVelocity.y, localVelocity.z); } } else if (localVelocity.x < 0) { localVelocity += new Vector3(SerializedFields.singleton.friction * 9.81f * simulationDeltaTime, 0, 0); if (localVelocity.x > 0) { localVelocity = new Vector3(0, localVelocity.y, localVelocity.z); } } if (!serverCarComponent.GoingBackward) { if (keyForwardPressed && !keyBackwardPressed) { if (localVelocity.z < 0) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.friction * 9.81f * simulationDeltaTime); } else { localVelocity += new Vector3(0, 0, SerializedFields.singleton.forwardAcceleration * simulationDeltaTime); } } else if (keyBackwardPressed && !keyForwardPressed) { if (localVelocity.z > 0) { localVelocity -= new Vector3(0, 0, SerializedFields.singleton.brakeAcceleration * simulationDeltaTime); if (localVelocity.z < 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } else if (localVelocity.z < 0) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.brakeAcceleration * simulationDeltaTime); if (localVelocity.z > 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } if (Vector3.ProjectOnPlane(localVelocity, Vector3.up).magnitude < 0.1f) { serverCarComponent.GoingBackward = true; } } else { if (localVelocity.z > 0) { localVelocity -= new Vector3(0, 0, SerializedFields.singleton.idleDeacceleration * simulationDeltaTime); if (localVelocity.z < 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } else if (localVelocity.z < 0) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.friction * 9.81f * simulationDeltaTime); if (localVelocity.z > 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } } } else { if (keyForwardPressed && !keyBackwardPressed) { if (localVelocity.z > 0) { localVelocity -= new Vector3(0, 0, SerializedFields.singleton.brakeAcceleration * simulationDeltaTime); if (localVelocity.z < 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } else if (localVelocity.z < 0) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.brakeAcceleration * simulationDeltaTime); if (localVelocity.z > 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } if (Vector3.ProjectOnPlane(localVelocity, Vector3.up).magnitude < 0.1f) { serverCarComponent.GoingBackward = false; } } else if (keyBackwardPressed && !keyForwardPressed) { if (localVelocity.z > -SerializedFields.singleton.backwardTopSpeed) { localVelocity -= new Vector3(0, 0, SerializedFields.singleton.backwardAcceleration * simulationDeltaTime); if (localVelocity.z < -SerializedFields.singleton.backwardTopSpeed) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, -SerializedFields.singleton.backwardTopSpeed); } } else if (localVelocity.z < -SerializedFields.singleton.backwardTopSpeed) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.brakeAcceleration * simulationDeltaTime); if (localVelocity.z > -SerializedFields.singleton.backwardTopSpeed) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, -SerializedFields.singleton.backwardTopSpeed); } } } else { if (localVelocity.z > 0) { localVelocity -= new Vector3(0, 0, SerializedFields.singleton.friction * 9.81f * simulationDeltaTime); if (localVelocity.z < 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } else if (localVelocity.z < 0) { if (localVelocity.z < -SerializedFields.singleton.backwardTopSpeed) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.friction * 9.81f * simulationDeltaTime); } else { localVelocity += new Vector3(0, 0, SerializedFields.singleton.idleDeacceleration * simulationDeltaTime); if (localVelocity.z > 0) { localVelocity = new Vector3(localVelocity.x, localVelocity.y, 0); } } } } } Vector3 localAngularVelocity = velocity.Angular; // no need to inverse transform if (localAngularVelocity.y > SerializedFields.singleton.maxAngularVelocity) { localAngularVelocity.y = SerializedFields.singleton.maxAngularVelocity; } else if (localAngularVelocity.y < -SerializedFields.singleton.maxAngularVelocity) { localAngularVelocity.y = -SerializedFields.singleton.maxAngularVelocity; } Vector3 transformUp = math.mul(rotation.Value, new float3(0, 1, 0)); float targetAngularVelocityY = Mathf.Min(Vector3.ProjectOnPlane(velocity.Linear, transformUp).magnitude / SerializedFields.singleton.minSpeedForFullRotation, 1) * carComponent.SteerAngle / SerializedFields.singleton.maxSteerAngle * SerializedFields.singleton.maxTurningAngularVelocity * (serverCarComponent.GoingBackward ? -1 : 1); if (targetAngularVelocityY > localAngularVelocity.y) { localAngularVelocity += new Vector3(0, SerializedFields.singleton.angularAcceleration * simulationDeltaTime, 0); if (localAngularVelocity.y > targetAngularVelocityY) { localAngularVelocity = new Vector3(localAngularVelocity.x, targetAngularVelocityY, localAngularVelocity.z); } } else if (targetAngularVelocityY < localAngularVelocity.y) { localAngularVelocity -= new Vector3(0, SerializedFields.singleton.angularAcceleration * simulationDeltaTime, 0); if (localAngularVelocity.y < targetAngularVelocityY) { localAngularVelocity = new Vector3(localAngularVelocity.x, targetAngularVelocityY, localAngularVelocity.z); } } localVelocity = Vector3.ProjectOnPlane(localVelocity, Vector3.forward) + Quaternion.AngleAxis(localAngularVelocity.y * simulationDeltaTime, Vector3.up) * Vector3.Project(localVelocity, Vector3.forward); if (EntityManager.GetComponentData <BoostComponent>(carEntity).RemainingTime > 0) { localVelocity += new Vector3(0, 0, SerializedFields.singleton.boostPowerupAcceleration * simulationDeltaTime); } velocity.Angular = localAngularVelocity; // no need to transform velocity.Linear = math.mul(rotation.Value, localVelocity); }); } }