public static void KeepInCube(Transform cube, float radius, Transform sphere) { if (!sphereInCube(sphere.position, radius, cube)) { Vector3 _ballLocalPosition = VectorOperator.getLocalPosition(cube, sphere.position); float displacementX1 = _ballLocalPosition.x + radius - 0.5f * cube.localScale.x; float displacementX2 = _ballLocalPosition.x - radius + 0.5f * cube.localScale.x; if (displacementX1 > 0.0f) { sphere.position -= displacementX1 * cube.right; } else if (displacementX2 < 0.0f) { sphere.position -= displacementX2 * cube.right; } float displacementZ1 = _ballLocalPosition.z + radius - 0.5f * cube.localScale.z; float displacementZ2 = _ballLocalPosition.z - radius + 0.5f * cube.localScale.z; if (displacementZ1 > 0.0f) { sphere.position -= displacementZ1 * cube.forward; } else if (displacementZ2 < 0.0f) { sphere.position -= displacementZ2 * cube.forward; } } }
void OnUpdade() { #if UNITY_EDITOR if (Application.isPlaying) { #endif if (connectedBody) { wheelPivot.position = VectorOperator.getWordPosition(absorber, localPosition); if (turnBody) { if (lineralDamper) { wheelPivot.transform.LookAt(wheelPivot.transform.position + steering.transform.up, -steering.transform.forward); } else { wheelPivot.LookAt(wheelPivot.position + Vector3.ProjectOnPlane(turnBody.transform.forward, root.up).normalized, root.up); } } float angularVelocityX = Vector3.Dot(body.angularVelocity, wheelPivot.right); if (Mathf.Abs(angularVelocityX) > 0.9f) { transform.RotateAround(wheelPivot.position, wheelPivot.right, (180.0f / Mathf.PI) * angularVelocityX * Time.deltaTime); } } #if UNITY_EDITOR } #endif }
public static void MoveBallInQuad(Transform cube, float radius, Vector3 hitPoint, ref Vector3 position) { if (sphereInCube(hitPoint, radius, cube)) { position = hitPoint; } else { Vector3 _ballMoveLocalPosition = VectorOperator.getLocalPosition(cube, hitPoint); if (!(Mathf.Abs(_ballMoveLocalPosition.x) <= -radius + 0.5f * cube.localScale.x)) { if (Mathf.Abs(_ballMoveLocalPosition.z) <= -radius + 0.5f * cube.localScale.z) { Vector3 ballMovePositionX = _ballMoveLocalPosition.x > 0.0f? VectorOperator.getWordPosition(cube, (-radius + 0.5f * cube.localScale.x) * Vector3.right): VectorOperator.getWordPosition(cube, (radius - 0.5f * cube.localScale.x) * Vector3.right); position = new Vector3(ballMovePositionX.x, position.y, hitPoint.z); } } else { if (Mathf.Abs(_ballMoveLocalPosition.x) <= -radius + 0.5f * cube.localScale.x) { Vector3 ballMovePositionZ = _ballMoveLocalPosition.z > 0.0f? VectorOperator.getWordPosition(cube, (-radius + 0.5f * cube.localScale.z) * Vector3.forward): VectorOperator.getWordPosition(cube, (radius - 0.5f * cube.localScale.z) * Vector3.forward); position = new Vector3(hitPoint.x, position.y, ballMovePositionZ.z); } } } }
public bool OnButton(RaycastHit curentHit) { if (!isSelected) { return(false); } if (curentHit.collider == GetComponent <Collider>() && Vector3.Distance(curentHit.point, strPosition) < radius) { touch.position = curentHit.point; } else { Vector3 displacement = curentHit.point - strPosition; touch.position = radius * (displacement - Vector3.Project(displacement, cueCamera.transform.forward)).normalized + strPosition; } displacementX = Mathf.Clamp((1.0f / radius) * VectorOperator.getLocalPosition(transform, touch.position).x, -1.0f, 1.0f); displacementZ = Mathf.Clamp((1.0f / radius) * VectorOperator.getLocalPosition(transform, touch.position).z, -1.0f, 1.0f); if (CircularSliderPress != null) { CircularSliderPress(this); } return(true); }
void Update() { if (controller.NewPoseName == "Rotate left" || controller.NewPoseName == "Rotate right" || controller.NewPoseName == "From Rotate left" || controller.NewPoseName == "From Rotate right" || controller.NewPoseName == "Left turn" || controller.NewPoseName == "Right turn") { position = VectorOperator.getWordPosition(aviator, localPosition); } else { position = deltaPosition + aviator.position; } //position = VectorOperator.getWordPosition(aviator, localPosition); if (controller.inAnimate) { _transform.position = Vector3.Lerp(_transform.position, position, 1.0f * damp * Time.deltaTime); } else { _transform.position = Vector3.Lerp(_transform.position, position, damp * Time.deltaTime); } aviatorPosition = Vector3.Lerp(aviatorPosition, aviator.position, 2.0f * damp * Time.deltaTime); _transform.LookAt(aviatorPosition); }
void Awake() { _transform = transform; deltaPosition = _transform.position - aviator.position; localPosition = VectorOperator.getLocalPosition(aviator, _transform.position); aviatorPosition = aviator.position; }
void Update() { if (parachuteIsOpened) { if (parachute.localScale.magnitude < parachuteStrSqale.magnitude) { parachute.localScale *= 1.0f + 5.0f * Time.deltaTime; for (i = 5; i < 11; i++) { joints [i].frequency = 0f; } } else { parachute.localScale = parachuteStrSqale; } } time += Time.deltaTime; if (time > 100000.0f) { time = 0.0f; } for (int i = 0; i < hipSuitPoints.Length; i++) { hipSuitPoints [i].localRotation = Quaternion.Euler(hipSuitRotations [i] + suitMagnitude * Mathf.Sin(suitFrequency * time + ((float)i)) * (Mathf.PI / 2.0f) * Vector3.right); } for (int i = 0; i < armSuits.Length; i++) { armSuits [i].localRotation = Quaternion.Euler(armSuitRotations [i] + 0.75f * suitMagnitude * Mathf.Sin(suitFrequency * time + ((float)i)) * (Mathf.PI / 2.0f) * Vector3.right); } if (!posController.inAnimate) { foreach (var item in joints) { item.AnimateJoint(); } } VelocityControl(); if (posController.NewPoseName == "Salto" || posController.NewPoseName == "From Salto") { velocity = velocityY * Vector3.up + velocityZ * VectorOperator.getProjectXZ(velocity.normalized, true); } else if (posController.NewPoseName == "Open parachute" || (parachuteIsOpened && posController.NewPoseName == "ParachuteDown") || (parachuteIsOpened && posController.NewPoseName == "ParachuteUp") || (parachuteIsOpened && posController.NewPoseName == "Parachute right") || (parachuteIsOpened && posController.NewPoseName == "Parachute left")) { velocity = velocityY * Vector3.up - velocityZ * root.up; if (posController.NewPoseName == "ParachuteDown") { velocity = velocityY * Vector3.up - velocityZ * root.up * 2f; } } else { velocity = velocityY * Vector3.up + velocityZ * root.forward; } velocity *= 9.0f; transform.position += velocity * Time.deltaTime; transform.Rotate(rotationY * Time.deltaTime * Vector3.up); }
void LateUpdate() { if (!downDetailParent) { enabled = false; return; } springDownDetail.position = VectorOperator.getWordPosition(downDetailParent, localPosition); springDownDetail.LookAt(springUpDetail.position); springUpDetail.LookAt(springDownDetail.position); float deltaDistance = Vector3.Distance(downPivot.position, upPivot.position) / detailsStartDistance; spring.localScale = new Vector3(springStartScale.x, springStartScale.y, springStartScale.z * deltaDistance); }
public void SetParent(Transform upDetailParent, Transform downDetailParent) { if (!springDownDetail || !springUpDetail || !spring || !downPivot || !upPivot) { enabled = false; return; } springUpDetail.parent = upDetailParent; springDownDetail.parent = upDetailParent; this.downDetailParent = downDetailParent; if (!downDetailParent) { enabled = false; return; } localPosition = VectorOperator.getLocalPosition(downDetailParent, springDownDetail.position); }
void OnEnable() { vehicle = transform.GetComponentInParent <Vehicle>(); root = vehicle.transform; wheelPivot = transform.parent; #if UNITY_EDITOR if (!Application.isPlaying) { if (!body) { GameObject wheel = new GameObject(name + "_Joint"); GameObject wheelTurn = null; if (wheelPivot.name.Contains("WheelTurn")) { wheelTurn = new GameObject(name + "_Turn_Joint"); steering = root.GetComponentInChildren <Steering>(); } Transform physics = root.Find("Physics"); if (!physics) { physics = new GameObject("Physics").transform; physics.parent = root.transform; physics.position = root.position; physics.transform.localScale = Vector3.one; } wheel.transform.parent = physics; wheel.transform.position = transform.position; wheel.transform.rotation = root.rotation; if (wheelTurn) { wheelTurn.transform.parent = physics; wheelTurn.transform.position = wheelPivot.position; lineralDamper = GetComponentInParent <Absorber>(); if (!lineralDamper.name.Contains("LineralAbsorber")) { lineralDamper = null; } if (lineralDamper) { wheelTurn.transform.LookAt(wheelTurn.transform.position + steering.transform.up, -steering.transform.forward); } else { wheelTurn.transform.rotation = root.rotation; } } joint = wheel.AddComponent <HingeJoint>(); bodyCollider = wheel.AddComponent <MeshCollider>(); body = wheel.GetComponent <Rigidbody>(); PhysicMaterial physicMaterial = (PhysicMaterial)AssetDatabase.LoadAssetAtPath("Assets/Vehicles/WheelSystem/PhysicsMaterials/Wheel.physicMaterial", typeof(PhysicMaterial)); parameters = new Parameters(name, true, true, 2.0f, 0.0f, 0.0f, physicMaterial); joint.anchor = Vector3.zero; joint.axis = Vector3.right; if (wheelTurn) { turnJoint = wheelTurn.AddComponent <HingeJoint>(); turnBody = wheelTurn.GetComponent <Rigidbody>(); turnBody.mass = parameters.mass; turnJoint.anchor = Vector3.zero; turnJoint.axis = Vector3.up; UpdateSteeringParameters(); } if (!turnJoint) { Absorber aAbsorber = transform.GetComponentInParent <Absorber>(); if (aAbsorber) { connectedBody = aAbsorber.body; absorber = aAbsorber.transform; } else { connectedBody = root.GetComponent <Rigidbody>(); absorber = root; } } else { Absorber aAbsorber = transform.GetComponentInParent <Absorber>(); if (aAbsorber) { turnJoint.connectedBody = aAbsorber.body; absorber = aAbsorber.transform; } else { turnJoint.connectedBody = root.GetComponent <Rigidbody>(); absorber = root; } connectedBody = turnBody; } joint.connectedBody = connectedBody; //absorber = connectedBody.transform; horsepower = 10.0f; maxVelocityMPS = 55.0f; newtonMeterPerSecond = 746.0f * horsepower; tractionForce = newtonMeterPerSecond / maxVelocityMPS; CalculateCollider(); } } else { #endif if (!absorber) { enabled = false; return; } newtonMeterPerSecond = 746.0f * horsepower; tractionForce = newtonMeterPerSecond / maxVelocityMPS; radius = 0.5f * body.transform.lossyScale.y; body.maxAngularVelocity = maxVelocityMPS / radius; JointMotor motor = new JointMotor(); motor.targetVelocity = (180.0f / Mathf.PI) * velocityMPS / radius; motor.force = tractionForce * radius;; joint.motor = motor; Absorber aAbsorber = transform.GetComponentInParent <Absorber>(); if (aAbsorber) { aAbsorber.OnUpdade += OnUpdade; } else if (vehicle) { vehicle.OnUpdade += OnUpdade; } if (connectedBody) { localPosition = VectorOperator.getLocalPosition(absorber, wheelPivot.position); wheelPivot.parent = root; } foreach (var item in root.GetComponentsInChildren <Collider>()) { Physics.IgnoreCollision(bodyCollider, item); } #if UNITY_EDITOR } #endif }
// this function is doing awefully little, only works some sounds and work with the main ball // in here, we use reserve velocity all we want but NEVER set it void OnCollisionEnter(Collision collision) { // dajiang physics 2 // we need angular velocity and real velocity for both items before. // we need frictions of the 2 contact surfaces (this is already known through the layerName). // reserveVelocity stuff is the backup, which I will NOT change in this function but only change in fixedupdate // we need to make sure the exit velocities of the 2 balls are perpendicular to each other // you can and do have an initial angular velocity, and in some cases it immediately matches with your real velocity // we can set a flag so we know if the real rigidbody.velocity is modified upon impact or not at each frame // if it has not been impacted, we will swap in the new values // if it has been impacted, we will apply the new value on top of it // velocity of the rigidbody right now is already calculated by unity for after the collision // if we want to update it any further (or in case of wall, not updated), we can do our calculation here. // angular is immediately reconciled for wall collisions and should be reconciles quickly for normal hits except for skidding (which can last some time). string layerName = LayerMask.LayerToName(collision.collider.gameObject.layer); // An important pre-condition // If we get a stationary ball to ball or ball to wall collision due to initial game setting, we need to ignore those collisions because they do crazy things if ((layerName == "Wall" || layerName == "Ball" || layerName == "MainBall") && collision.relativeVelocity.magnitude > 0.01f) { if (layerName == "Ball" || layerName == "MainBall") // ballllzzz { BallController otherBall = collision.collider.gameObject.GetComponent <BallController>(); if (otherBall && otherBall.id < id) { // sound portion for ball on ball float b_b_volume = Mathf.Clamp01(collision.relativeVelocity.magnitude / cueController.ballMaxVelocity); int b_b_index = 0; if (b_b_volume > 0.66f) { b_b_index = Random.Range((int)MusicClip.B_B_Hard_0, (int)MusicClip.B_B_Hard_2 + 1); } else if (b_b_volume > 0.33f) { b_b_index = Random.Range((int)MusicClip.B_B_Mid_0, (int)MusicClip.B_B_Mid_1 + 1); } else { b_b_index = Random.Range((int)MusicClip.B_B_Weak_0, (int)MusicClip.B_B_Weak_1 + 1); } GameManager_script.Instance().PlaySound(b_b_index, false, b_b_volume); } // real physics stuff starts here if (inMove && cueController && collision.collider.GetComponent <Rigidbody>()) { Vector3 exitVelocity = Vector3.zero; float energyRetained = 0.0f; // object ball with a spline attached (risky but necessary for a successful game) // has to be the first contact if (otherBall.isMain && cueController.CurrentBallID == id && cueController.TargetPocketDirection != Vector3.zero) { // assign collision normal exitVelocity = cueController.TargetPocketDirection; // zero out stuff so there is no next use cueController.TargetPocketDirection = Vector3.zero; cueController.CurrentBallID = -1; // calculate energy retained energyRetained = Vector3.Dot((cueController.currentHitBallController.reserveVelocity + cueController.cueBallController.reserveVelocity).normalized, exitVelocity.normalized); // the following are all copied from ball controller, make them into a function if (energyRetained < 0.0f) { energyRetained += 1; } if (!cueController.currentHitBallController.GetComponent <Rigidbody>().isKinematic) { cueController.currentHitBallController.GetComponent <Rigidbody>().velocity = exitVelocity.normalized * energyRetained * (cueController.cueBallController.reserveVelocity.magnitude + cueController.currentHitBallController.reserveVelocity.magnitude); } } // cue ball with its spline, this will always check out else if (isMain && cueController.CurrentBallID == otherBall.id && cueController.CueBallBounceDirection != Vector3.zero) { // assign collision normal exitVelocity = cueController.CueBallBounceDirection; // zero out the spline cueController.CueBallBounceDirection = Vector3.zero; // calculate energy retained energyRetained = Vector3.Dot((cueController.currentHitBallController.reserveVelocity + cueController.cueBallController.reserveVelocity).normalized, exitVelocity.normalized); // the following are all copied from ball controller, make them into a function if (energyRetained < 0.0f) { energyRetained += 1; } if (!cueController.cueBallController.GetComponent <Rigidbody>().isKinematic) { cueController.cueBallController.GetComponent <Rigidbody>().velocity = exitVelocity.normalized * energyRetained * (cueController.cueBallController.reserveVelocity.magnitude + cueController.currentHitBallController.reserveVelocity.magnitude); } } // all other cases of ball to ball collision else { // we use unity built in engine for this purpose exitVelocity = GetComponent <Rigidbody>().velocity; // zero out stuff so there is no next use cueController.TargetPocketDirection = Vector3.zero; cueController.CurrentBallID = -1; cueController.CueBallBounceDirection = Vector3.zero; // calculate energy retained energyRetained = exitVelocity.magnitude / (reserveVelocity.magnitude + otherBall.reserveVelocity.magnitude); // guard against negative numbers if (energyRetained < 0.0f) { energyRetained += 1; } if (!GetComponent <Rigidbody>().isKinematic) { GetComponent <Rigidbody>().velocity = exitVelocity.normalized * energyRetained * (reserveVelocity.magnitude + otherBall.reserveVelocity.magnitude); } } } // some game rules, you can only first hit the current first ball if (cueController.firstBallBallCollisionSinceShot && otherBall != null) { if (isMain || otherBall.isMain) { int tempId = 0; if (isMain) { tempId = otherBall.id; } else { tempId = id; } if (cueController.currentBallControllers.Count > 1) { if (tempId != cueController.currentBallControllers[1].id) // first ball remaining { cueController.hittingTheRightFirstBall = false; } else { cueController.hittingTheRightFirstBall = true; } } cueController.firstBallBallCollisionSinceShot = false; } } cueController.contactedAtLeastOneRealBall = true; } if (layerName == "Wall" && !GetComponent <Rigidbody>().isKinematic&& !ballIsPocketed) // walllllz, should include pocket walls { // choose sound float b_w_volume = Mathf.Clamp01(collision.relativeVelocity.magnitude / cueController.ballMaxVelocity); int b_w_index = Random.Range((int)MusicClip.B_W_0, (int)MusicClip.B_W_1 + 1); // play sound GameManager_script.Instance().PlaySound(b_w_index, false, b_w_volume); // take half a ball back to avoid the risk of running into the other side of the wall before our wall, vectoroperator has things that does this as well Ray ray = new Ray(GetComponent <Rigidbody>().position - cueController.ballRadius * reserveVelocity.normalized * 1.25f, reserveVelocity.normalized); RaycastHit hit; // use a common angular velocity bullshit Vector3 reserveXZVelocity = VectorOperator.getProjectXZ(reserveVelocity, false); Vector3 reserveXZAngularVelocity = VectorOperator.getProjectXZ(reserveAngularVelocity, false); if (Physics.SphereCast(ray, cueController.ballRadius, out hit, 20.0f * cueController.ballRadius, cueController.wallMask)) { // make sure we only have a bounce but no pocket direction, meaning it is not a ball hit if (isMain && cueController.CueBallBounceDirection != Vector3.zero && cueController.TargetPocketDirection == Vector3.zero) { // set the straight velocity up GetComponent <Rigidbody>().velocity = Vector3.Magnitude(reserveVelocity) * Vector3.Normalize(cueController.CueBallBounceDirection); // reset everything just to be sure cueController.TargetPocketDirection = Vector3.zero; cueController.CurrentBallID = -1; cueController.CueBallBounceDirection = Vector3.zero; } else { // calculate linear velocity GetComponent <Rigidbody>().velocity = reserveXZVelocity - 2.0f * Vector3.Project(reserveXZVelocity, VectorOperator.CleanYAxis(-hit.normal)); GetComponent <Rigidbody>().velocity = VectorOperator.getProjectXZ(GetComponent <Rigidbody>().velocity, true); } if (true) { // calculate angular velocity Vector3 XZHitNormal = VectorOperator.CleanYAxis(-hit.normal); // this declaration is f*****g retarded float XAngular = reserveXZAngularVelocity.x; float ZAngular = reserveXZAngularVelocity.z; // z is NOT flat, so x needs to be re-calculated. Since reserve velocity x is always negative of the reserve angular z, so we add. if (Mathf.Abs(XZHitNormal.x) > 0.01f) { ZAngular += Mathf.Abs(XZHitNormal.x) * reserveVelocity.x * 2.0f * 2.0f; // 2.0f for twice the angular, 2.0f for negation ZAngular = Mathf.Clamp(ZAngular, Mathf.Abs(reserveXZAngularVelocity.z) * -1.0f, Mathf.Abs(reserveXZAngularVelocity.z) * 1.0f); // dajiang hack, i omitted the other component, make sure ZAngular doesn't exceed the total magnitude it previously had } // x is NOT flat, so z needs to be re-calculated. Since reserve velocity z is always in sync with reserve angluar x, so we subtract. if (Mathf.Abs(XZHitNormal.z) > 0.01f) { XAngular -= Mathf.Abs(XZHitNormal.z) * reserveVelocity.z * 2.0f * 2.0f; // 2.0f for twice the angular, 2.0f for negation XAngular = Mathf.Clamp(ZAngular, Mathf.Abs(reserveXZAngularVelocity.x) * -1.0f, Mathf.Abs(reserveXZAngularVelocity.x) * 1.0f); // dajiang hack, i omitted the other component, make sure XAngular doesn't exceed the total magnitude it previously had } GetComponent <Rigidbody>().angularVelocity = new Vector3(XAngular, 0.0f, ZAngular); } // add Y component of angular velocity to linear velocity and subtract itself from the angular component, dajiang hack? Donno what this is no more Vector3 YAngularVelocityOnly = new Vector3(0.0f, reserveAngularVelocity.y, 0.0f); // actually add and subtract angular velocities GetComponent <Rigidbody>().velocity += 0.36f * Vector3.Magnitude(YAngularVelocityOnly * 0.5f) * Vector3.Cross(VectorOperator.CleanYAxis(-hit.normal), YAngularVelocityOnly.normalized); GetComponent <Rigidbody>().angularVelocity -= new Vector3(0.0f, 0.36f * reserveAngularVelocity.y, 0.0f); // this line checks out // calculate restitution cooef, 1 is straight, 0 is slice float impactAngle = Mathf.Clamp01(Vector3.Dot(reserveXZVelocity.normalized, VectorOperator.CleanYAxis(-hit.normal).normalized)); // restitution, choose wisely GetComponent <Rigidbody>().velocity = (0.96f - impactAngle * 0.24f) * GetComponent <Rigidbody>().velocity; GetComponent <Rigidbody>().angularVelocity = (0.96f - impactAngle * 0.24f) * GetComponent <Rigidbody>().angularVelocity; } // only start counting the wall hits after a good ball hit, otherwise all wall hits are pointless if (cueController.contactedAtLeastOneRealBall) { cueController.wallHitCount += 1; } } } }