Skip to content

Instantly share code, notes, and snippets.

@stilllisisi
Last active March 11, 2020 08:30
Show Gist options
  • Save stilllisisi/5daf702f747bef69e5a89c7d48269a51 to your computer and use it in GitHub Desktop.
Save stilllisisi/5daf702f747bef69e5a89c7d48269a51 to your computer and use it in GitHub Desktop.
【游戏-unity】Unity实现水面漂浮效果。以unity的StandardAssets中的water资源为基础,介绍物体在水中的漂浮效果实现。
//1.给水体添加碰撞体
//需要注意的是要勾选Is Trigger,y方向的范围要控制好,不然可能会出现物体掉到水面一下太多会触发OnTriggerExit()(见脚本部分)。
//2.创建立方体
//创建一个长宽高分别为1,质量为0.5的立方体,预期效果是在水中漂浮一半露出水面。之后可以通过脚本改变大小及质量验证效果。
//3.水的脚本
//水的脚本主要实现OnTriggerEnter和OnTriggerExit两个方法,当其他碰撞体进入水中,触发OnTriggerEnter,将cube中的isInWater置为ture,OnTriggerExit相反。
//4.立方体脚本
//立方体脚本的核心是calFloatage方法,计算立方体下表面与水面高度差,通过公式计算浮力,并通过Rigidbody.AddForce()方法施加浮力。
//进入水中后将阻力系数调高。注意物体完全进入水中后保持h=立方体高度
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Floatage : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
/// <summary>
/// OnTriggerEnter is called when the Collider other enters the trigger.
/// </summary>
/// <param name="other">The other Collider involved in this collision.</param>
void OnTriggerEnter(Collider other)
{
if(other.gameObject.GetComponent<Cube>()){
other.gameObject.GetComponent<Cube>().setIsInWater(true);
}
}
/// <summary>
/// OnTriggerExit is called when the Collider other has stopped touching the trigger.
/// </summary>
/// <param name="other">The other Collider involved in this collision.</param>
void OnTriggerExit(Collider other)
{
if(other.gameObject.GetComponent<Cube>()){
other.gameObject.GetComponent<Cube>().setIsInWater(false);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cube : MonoBehaviour {
private bool isInWater;
private GameObject water;
private float waterY;
private const float floatageForce = 0;
private const float density = 1;
private const float g = 9.8f;
private const float waterDrag = 5;
public bool getIsInWater(){
return isInWater;
}
public void setIsInWater(bool isInWater){
this.isInWater = isInWater;
}
// Use this for initialization
void Start () {
isInWater = false;
water = GameObject.FindWithTag("water");
}
// Update is called once per frame
void Update () {
}
/// <summary>
/// This function is called every fixed framerate frame, if the MonoBehaviour is enabled.
/// </summary>
void FixedUpdate()
{
if(isInWater){
//calculate floatage
calFloatage();
//change darg
GetComponent<Rigidbody>().drag = waterDrag;
}
}
//calculate and add floatage force to the box.
private void calFloatage(){
waterY = water.transform.position.y;
if(waterY>(transform.position.y-transform.localScale.y)){
float h = waterY-(transform.position.y-transform.localScale.y/2)>transform.localScale.y? transform.localScale.y:waterY-(transform.position.y-transform.localScale.y/2);
float floatageForce = density * g *transform.localScale.x*transform.localScale.z*h;
GetComponent<Rigidbody>().AddForce(0,floatageForce,0);
}
}
}
@stilllisisi
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment