You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
8.1 KiB
C#
305 lines
8.1 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
|
|
namespace Suimono.Core
|
|
{
|
|
|
|
public class fx_buoyancy : MonoBehaviour {
|
|
|
|
|
|
//PUBLIC VARIABLES
|
|
public bool applyToParent = false;
|
|
public bool engageBuoyancy = false;
|
|
public float activationRange = 5000.0f;
|
|
public bool inheritForce = false;
|
|
public bool keepAtSurface = false;
|
|
public float buoyancyOffset = 0.0f;
|
|
public float buoyancyStrength = 1.0f;
|
|
public float forceAmount = 1.0f;
|
|
public float forceHeightFactor = 0.0f;
|
|
|
|
// PRIVATE VARIABLES
|
|
private float maxVerticalSpeed = 5.0f;
|
|
private float surfaceRange = 0.2f;
|
|
private float buoyancy = 0.0f;
|
|
private float surfaceLevel = 0.0f;
|
|
private float underwaterLevel = 0.0f;
|
|
private bool isUnderwater = false;
|
|
private Transform physTarget;
|
|
private Suimono.Core.SuimonoModule moduleObject;
|
|
private float waveHeight = 0.0f;
|
|
private float modTime = 0.0f;
|
|
private float splitFac = 1.0f;
|
|
private Rigidbody rigidbodyComponent;
|
|
private float isOver = 0.0f;
|
|
private Vector2 forceAngles = new Vector2(0.0f,0.0f);
|
|
private float forceSpeed = 0.0f;
|
|
private float waveHt = 0.0f;
|
|
//private float displace;
|
|
|
|
private int randSeed;
|
|
private Suimono.Core.Random buyRand;
|
|
|
|
//collect for GC
|
|
private Vector3 gizPos;
|
|
private float testObjectHeight;
|
|
private float buoyancyFactor;
|
|
private float forceMod;
|
|
private float waveFac;
|
|
private float[] heightValues;
|
|
private bool isEnabled = true;
|
|
private bool performHeight = false;
|
|
private float currRange = -1.0f;
|
|
//private float camRange = -1.0f;
|
|
//private Vector3 currCamPos = new Vector3(-1f,-1f,-1f);
|
|
private Vector3 physPosition;
|
|
private bool saveRigidbodyState;
|
|
private float lerpSurfacePosTime = 0f;
|
|
private float targetYPosition;
|
|
private float startYPosition;
|
|
private bool saveKeepAtSurface;
|
|
|
|
|
|
void OnDrawGizmos (){
|
|
gizPos = transform.position;
|
|
gizPos.y += 0.03f;
|
|
Gizmos.DrawIcon(gizPos, "gui_icon_buoy.psd", true);
|
|
gizPos.y -= 0.03f;
|
|
}
|
|
|
|
|
|
|
|
void Start () {
|
|
|
|
if (GameObject.Find("SUIMONO_Module") != null){
|
|
moduleObject = (Suimono.Core.SuimonoModule) FindObjectOfType(typeof(Suimono.Core.SuimonoModule));
|
|
}
|
|
|
|
//set random
|
|
randSeed = System.Environment.TickCount;
|
|
buyRand = new Suimono.Core.Random(randSeed);
|
|
|
|
//get number of buoyant objects
|
|
if (applyToParent){
|
|
var buoyancyObjects = transform.parent.gameObject.GetComponentsInChildren<fx_buoyancy>();
|
|
if (buoyancyObjects != null){
|
|
splitFac = 1f/buoyancyObjects.Length;
|
|
}
|
|
}
|
|
|
|
//set physics target
|
|
if (applyToParent){
|
|
physTarget = this.transform.parent.transform;
|
|
if (physTarget != null){
|
|
if (rigidbodyComponent == null){
|
|
rigidbodyComponent = physTarget.GetComponent<Rigidbody>();
|
|
}}
|
|
} else {
|
|
physTarget = this.transform;
|
|
if (physTarget != null){
|
|
if (rigidbodyComponent == null){
|
|
rigidbodyComponent = GetComponent<Rigidbody>();
|
|
}}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void FixedUpdate(){
|
|
|
|
SetUpdate();
|
|
|
|
//Determine Vertical Speed
|
|
if (isUnderwater == false){
|
|
maxVerticalSpeed = 0.25f;
|
|
|
|
} else if (isUnderwater == true){
|
|
maxVerticalSpeed = Mathf.Clamp(surfaceLevel - (transform.position.y+buoyancyOffset-0.5f),0.0f,5.0f);
|
|
if (maxVerticalSpeed > 4.0f) maxVerticalSpeed = 4.0f;
|
|
}
|
|
|
|
//Set Buoyancy
|
|
buoyancy = 1 + (maxVerticalSpeed * buoyancyStrength);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SetUpdate () {
|
|
|
|
|
|
if (moduleObject != null){
|
|
|
|
//set Random
|
|
if (buyRand == null) buyRand = new Suimono.Core.Random(randSeed);
|
|
|
|
//check activations
|
|
performHeight = true;
|
|
if (physTarget != null && moduleObject.setCamera != null){
|
|
|
|
//check for range activation
|
|
if (activationRange > 0f){
|
|
currRange = Vector3.Distance(moduleObject.setCamera.transform.position, physTarget.transform.position);
|
|
if (currRange >= activationRange){
|
|
performHeight = false;
|
|
}
|
|
}
|
|
|
|
if (activationRange <= 0f) performHeight = true;
|
|
|
|
/*
|
|
//check for frustrum activation
|
|
camRange = 0.2f;
|
|
if (moduleObject != null && performHeight){
|
|
if (moduleObject.setCameraComponent != null){
|
|
currCamPos = moduleObject.setCameraComponent.WorldToViewportPoint(physTarget.transform.position);
|
|
if (currCamPos.x > (1f+camRange) || currCamPos.y > (1f+camRange)){
|
|
performHeight = false;
|
|
}
|
|
if (currCamPos.x < (0f-camRange) || currCamPos.y < (0f-camRange)){
|
|
performHeight = false;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
//check for enable activation
|
|
if (!isEnabled){
|
|
performHeight = false;
|
|
}
|
|
}
|
|
|
|
|
|
//perform height check
|
|
if (performHeight){
|
|
// Get all height variables from Suimono Module object
|
|
heightValues = moduleObject.SuimonoGetHeightAll(this.transform.position);
|
|
isOver = heightValues[4];
|
|
waveHt = heightValues[8];
|
|
surfaceLevel = heightValues[0];
|
|
forceAngles = moduleObject.SuimonoConvertAngleToVector(heightValues[6]);
|
|
forceSpeed = heightValues[7]*0.1f;
|
|
}
|
|
|
|
//clamp variables
|
|
forceHeightFactor = Mathf.Clamp01(forceHeightFactor);
|
|
|
|
//Reset values
|
|
isUnderwater = false;
|
|
underwaterLevel = 0f;
|
|
|
|
//calculate scaling
|
|
testObjectHeight = (transform.position.y+buoyancyOffset-0.5f);
|
|
|
|
waveHeight = surfaceLevel;
|
|
if (testObjectHeight < waveHeight){
|
|
isUnderwater = true;
|
|
}
|
|
underwaterLevel = waveHeight-testObjectHeight;
|
|
|
|
|
|
//set buoyancy
|
|
if (!keepAtSurface && rigidbodyComponent) rigidbodyComponent.isKinematic = saveRigidbodyState;
|
|
|
|
if (!keepAtSurface && engageBuoyancy && isOver == 1f){
|
|
if (rigidbodyComponent && !rigidbodyComponent.isKinematic){
|
|
|
|
//reset rigidbody if turned off
|
|
if (rigidbodyComponent.isKinematic){
|
|
rigidbodyComponent.isKinematic = saveRigidbodyState;
|
|
}
|
|
|
|
buoyancyFactor = 10.0f;
|
|
|
|
if (isUnderwater){
|
|
|
|
if (this.transform.position.y+buoyancyOffset-0.5f < waveHeight-surfaceRange){
|
|
|
|
// add vertical force to buoyancy while underwater
|
|
forceMod = (buoyancyFactor * (buoyancy * rigidbodyComponent.mass) * (underwaterLevel) * splitFac * (isUnderwater ? 1f : 0f) );
|
|
if (rigidbodyComponent.velocity.y < maxVerticalSpeed){
|
|
rigidbodyComponent.AddForceAtPosition(new Vector3(0f,1f,0f) * forceMod, transform.position);
|
|
}
|
|
|
|
modTime = 0f;
|
|
|
|
} else {
|
|
|
|
// slow down vertical velocity as it reaches water surface or wave zenith
|
|
modTime = (this.transform.position.y+buoyancyOffset-0.5f) / (waveHeight+buyRand.Next(0f,0.25f) * (isUnderwater ? 1f : 0f));
|
|
if (rigidbodyComponent.velocity.y > 0f){
|
|
rigidbodyComponent.velocity = new Vector3(
|
|
rigidbodyComponent.velocity.x,
|
|
Mathf.SmoothStep(rigidbodyComponent.velocity.y,0f,modTime),
|
|
rigidbodyComponent.velocity.z);
|
|
}
|
|
}
|
|
|
|
|
|
//Add Water Force / Direction to Buoyancy Object
|
|
if (inheritForce){
|
|
if (this.transform.position.y+buoyancyOffset-0.5f <= waveHeight){
|
|
waveFac = Mathf.Lerp(0f,forceHeightFactor,waveHt);
|
|
if (forceHeightFactor == 0f) waveFac = 1f;
|
|
rigidbodyComponent.AddForceAtPosition(new Vector3(forceAngles.x,0f,forceAngles.y) * (buoyancyFactor*2f) * forceSpeed * waveFac * splitFac * forceAmount, transform.position);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//Keep At Surface Option
|
|
if (keepAtSurface && isOver == 1f){
|
|
|
|
|
|
|
|
saveKeepAtSurface = keepAtSurface;
|
|
float testPos = (surfaceLevel - physTarget.position.y - buoyancyOffset);
|
|
if ( testPos >= -0.25f){
|
|
|
|
//remove rigidbody
|
|
if (rigidbodyComponent != null){
|
|
//rigidbodyComponent.velocity = Vector3.zero;
|
|
if (!rigidbodyComponent.isKinematic){
|
|
saveRigidbodyState = false;
|
|
rigidbodyComponent.isKinematic = true;
|
|
}
|
|
}
|
|
|
|
//set Y position
|
|
physPosition = physTarget.position;
|
|
physPosition.y = Mathf.Lerp(startYPosition, targetYPosition, lerpSurfacePosTime);
|
|
physTarget.position = physPosition;
|
|
|
|
} else {
|
|
rigidbodyComponent.isKinematic = saveRigidbodyState;
|
|
}
|
|
|
|
|
|
//set timer for smooth blend
|
|
lerpSurfacePosTime += Time.deltaTime * 4f;
|
|
if (lerpSurfacePosTime > 1f || keepAtSurface != saveKeepAtSurface){
|
|
lerpSurfacePosTime = 0f;
|
|
startYPosition = physTarget.position.y;
|
|
targetYPosition = surfaceLevel - buoyancyOffset;//physTarget.position.y;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
} |