// Undo objects to previous state private void Undo() { if (undoCount <= 0) { return; } undoCount--; stepIndex--; if (stepIndex < 0) { stepIndex = STORAGE_SIZE - 1; } for (int i = 0; i < rigidBodies.Length; i++) { NewRigidBody rigidBody = rigidBodies [i]; RigidbodyState state = storage [stepIndex].states [i]; rigidBody.acceleration = state.acceleration; rigidBody.velocity = state.velocity; rigidBody.position = state.position; rigidBody.angularVelocity = state.angularVelocity; rigidBody.orientation = state.orientation; rigidBody.transform.rotation = Quaternion.Euler(state.orientation); rigidBody.transform.position = rigidBody.position; } }
// Store current state of objects private void StoreState() { RigidbodyState[] objectStates = new RigidbodyState[rigidBodies.Length]; for (int i = 0; i < rigidBodies.Length; i++) { NewRigidBody rigidBody = rigidBodies[i]; RigidbodyState state = new RigidbodyState(); state.acceleration = rigidBody.acceleration; state.velocity = rigidBody.velocity; state.position = rigidBody.position; state.angularVelocity = rigidBody.angularVelocity; state.orientation = rigidBody.transform.rotation.eulerAngles; objectStates[i] = state; } storage[stepIndex].states = objectStates; undoCount++; if (undoCount >= STORAGE_SIZE) { undoCount = STORAGE_SIZE - 1; } stepIndex++; if (stepIndex >= STORAGE_SIZE) { stepIndex = 0; } }
void PositionCorrection(NewRigidBody a, NewRigidBody b, float penetrationDepth, Vector3 collisionNormal) { // reference on how to correct position once an impulse is applied // https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331 const float percent = 0.8f; const float thresholdToPreventJitter = 0.01f; Vector3 correction = Mathf.Max(penetrationDepth - thresholdToPreventJitter, 0.0f) / (a._inverseMass + b._inverseMass) * percent * collisionNormal; // Apply if (a._isKinematic == false) { a.position -= a._inverseMass * correction; } if (b._isKinematic == false) { b.position += b._inverseMass * correction; } }
// Reset objects to the initial state public void Reset() { for (int i = 0; i < rigidBodies.Length; i++) { NewRigidBody rigidBody = rigidBodies [i]; RigidbodyState state = _initialStates[i]; rigidBody.acceleration = state.acceleration; rigidBody.velocity = state.velocity; rigidBody.position = state.position; rigidBody.angularVelocity = state.angularVelocity; rigidBody.orientation = state.orientation; rigidBody.transform.rotation = Quaternion.Euler(state.orientation); rigidBody.transform.position = rigidBody.position; rigidBody.transform.GetComponent <MeshRenderer> ().material = rigidBody._originalMaterial; } firstPlay = false; _initialConditions.SetActive(true); pause = true; }
void Update() { // Initial refresh if (_start == false) { _massInput.text = _selectedObject.mass.ToString(); _positionX.text = _selectedObject.position.x.ToString(); _positionY.text = _selectedObject.position.y.ToString(); _positionZ.text = _selectedObject.position.z.ToString(); _orienX.text = _selectedObject.orientation.x.ToString(); _orienY.text = _selectedObject.orientation.y.ToString(); _orienZ.text = _selectedObject.orientation.z.ToString(); _isKinematic.isOn = _selectedObject._isKinematic; _start = true; } // Prevent ray from going through UI if (EventSystem.current.IsPointerOverGameObject()) { return; } // Select object if (Input.GetKeyDown(KeyCode.Mouse0)) { RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 100.0f)) { _selectedObject = hit.transform.gameObject.GetComponent <NewRigidBody> (); _massInput.text = _selectedObject.mass.ToString(); _positionX.text = _selectedObject.position.x.ToString(); _positionY.text = _selectedObject.position.y.ToString(); _positionZ.text = _selectedObject.position.z.ToString(); _orienX.text = _selectedObject.orientation.x.ToString(); _orienY.text = _selectedObject.orientation.y.ToString(); _orienZ.text = _selectedObject.orientation.z.ToString(); _isKinematic.isOn = _selectedObject._isKinematic; RefreshUI(); } } // Apply torque if (Input.GetKey(KeyCode.Mouse1)) { RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 100.0f)) { hit.transform.gameObject.GetComponent <NewRigidBody> ().ApplyTorqueForce(hit.point, hit.normal); } } if (_selectedObject == null) { return; } // Refresh the selected object's UI RefreshUI(); }