Last active
March 11, 2020 08:30
-
-
Save stilllisisi/5daf702f747bef69e5a89c7d48269a51 to your computer and use it in GitHub Desktop.
【游戏-unity】Unity实现水面漂浮效果。以unity的StandardAssets中的water资源为基础,介绍物体在水中的漂浮效果实现。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://gameinstitute.qq.com/community/detail/128724