using System; using System.Collections; using System.Collections.Generic; using UnityEngine; [SelectionBase] public class LeafPhysics : MonoBehaviour { private Rigidbody body; public Rigidbody Body { get { return body; } } private LeafHandler leafHandler; private List<Material> mats = new List<Material>(); public IEnumerable<Material> Mats { get { return mats; } } // Use this for initialization void Start () { body = GetComponentInChildren<Rigidbody>(); PlusX = new TweeningForce(0, 1, 0.5f, 2); MinusX = new TweeningForce(0, 1, 0.5f, 2); PlusZ = new TweeningForce(0, 1, 0.5f, 2); MinusZ = new TweeningForce(0, 1, 0.5f, 2); TorqueX = new TweeningForce(-1, 1, 0.5f, 2); TorqueZ = new TweeningForce(-1, 1, 0.5f, 2); leafHandler = GameObject.FindObjectOfType<LeafHandler>(); if (leafHandler != null) { leafHandler.AddLeaf(this); } deadLifeSpan = UnityEngine.Random.Range(20, 40.0f); deadLife = deadLifeSpan; foreach (MeshRenderer mr in GetComponentsInChildren<MeshRenderer>()) { mats.Add(mr.material); } Color c = Color.white; c.r = UnityEngine.Random.Range(0.6f, 1.0f); c.g = UnityEngine.Random.Range(0.6f, 1.0f); c.b = UnityEngine.Random.Range(0.6f, 1.0f); foreach (Material m in mats) { m.color = c; } } void OnDestroy() { if (leafHandler != null) { leafHandler.RemoveLeaf(this); } } //public float TorqueForceUpScale = 0.3f; public float TorqueScale = 1.0f; public float TorqueBounds = 5.0f; public float TorqueSideScale = 1.0f; public float SideRestitution = 0.5f; //public float MaxForceUp = 1.0f; // //public float VelDownForceScale = 0.5f; //public float VelDownForceDivide = 3f; // //public float StartPushVelDown = 3.0f; //public float PushUpCurrent = 0; //public float PushUpForce = 10; //public float PushUpDecayRate = 1; public bool Debug = false; private TweeningForce PlusX; private TweeningForce MinusX; private TweeningForce PlusZ; private TweeningForce MinusZ; private TweeningForce TorqueX; private TweeningForce TorqueZ; private class TweeningForce { private float min, max, minMoveSpeed, maxMoveSpeed, current, target, speed; public float Current { get { return current; } } public TweeningForce(float min, float max, float minMoveSpeed, float maxMoveSpeed) { this.min = min; this.max = max; this.minMoveSpeed = minMoveSpeed; this.maxMoveSpeed = maxMoveSpeed; this.current = UnityEngine.Random.Range(min, max); UpdateTarget(); } private void UpdateTarget() { this.target = UnityEngine.Random.Range(min, max); this.speed = UnityEngine.Random.Range(minMoveSpeed, maxMoveSpeed); } public void Update(float timeElapsed) { float moveAmount = speed * timeElapsed; if (moveAmount >= Math.Abs(current - target)) { current = target; UpdateTarget(); } else { float move = Math.Max(-moveAmount, Math.Min(moveAmount, target - current)); current += move; } } } public float BaseWindForce = 10; public float AnglePow = 2; private float deadLife = 0; private float deadLifeSpan = 1; private bool isFading = false; public bool Resting = false; private void FixedUpdate() { Resting = false; } private void OnCollisionStay(Collision collision) { Resting = collision.contacts.Length > 0 && Mathf.Abs(collision.contacts[0].normal.y) > 0.7f; } // Update is called once per frame void Update () { if (!body.isKinematic && body.velocity.sqrMagnitude > 0.01f) { deadLife = deadLifeSpan; float baseForceUp = Mathf.Max(BaseWindForce * Mathf.Pow(Mathf.Abs(transform.up.y), AnglePow) * -body.velocity.y) * Time.deltaTime * 60; body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + PlusX.Current), transform.position + Vector3.right * 0.4f); body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + MinusX.Current), transform.position - Vector3.right * 0.4f); body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + PlusZ.Current), transform.position + Vector3.forward * 0.4f); body.AddForceAtPosition(Vector3.up * baseForceUp * (1 + MinusZ.Current), transform.position - Vector3.forward * 0.4f); /* if (body.velocity.y < -StartPushVelDown) { PushUpCurrent = PushUpForce; } body.AddForce(Vector3.up * PushUpCurrent); PushUpCurrent = Mathf.Max(0, PushUpCurrent - PushUpDecayRate * Time.deltaTime); */ Vector3 up = transform.up; float torqueX = -up.x; float torqueZ = -up.z; float velYScale = Math.Max(0, -body.velocity.y); body.AddRelativeForce(new Vector3(torqueX * TorqueSideScale, 0, torqueZ * TorqueSideScale) * velYScale); //body.AddForce(Vector3.up * Mathf.Pow(Mathf.Max(-body.velocity.y / VelDownForceDivide), 2) * VelDownForceScale); body.AddRelativeTorque(new Vector3(Mathf.Max(-TorqueBounds, Mathf.Min(TorqueBounds, torqueX * TorqueScale * 1.2f)) + TorqueX.Current * 0.5f, 0, Mathf.Max(-TorqueBounds, Mathf.Min(TorqueBounds, torqueZ * TorqueScale)) + TorqueZ.Current * 0.5f) * velYScale); body.AddForce(new Vector3(-body.velocity.x, 0, -body.velocity.z) * SideRestitution * Time.deltaTime * 60); } else { deadLife -= Time.deltaTime * (leafHandler.NumLeaves >= leafHandler.MaxLeaves ? 3 : 1); if (deadLife <= 0 && !isFading) { isFading = true; SimpleTween tweenOut = new SimpleTween(); tweenOut.Init(v => { foreach (Material m in mats) { Color c = m.color; c.a = v; m.color = c; } }, SimpleTween.EaseLinear, 1, 0, 2); GameObject t = this.gameObject; tweenOut.OnFinish = () => { Destroy(t); }; Destroy(this); } } if (transform.position.y < -5) { Destroy(gameObject); } } }