通过对官方文档查询,可以确定unity本身应该是不能对单个物体设置重力的,只能通过Physics的Gravity设置全局的重力,而Rigidbody只能通过useGravity来决定是否受重力影响,不过后来我想到可以通过施加额外的加速度来补正全局的的重力加速度,就可以将重力设为任意值了,机智哈哈~
经测试设想是可行的。效果如图:
非常ok,一个文件即实现,源码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class GravityControlHelper
{
/// <summary>
/// 设置物体的重力加速度
/// </summary>
public static void SetGravity(this GameObject obj, Vector3 val)
{
var c = obj.GetComponent<GravityControl>();
if (c == null)
c = obj.AddComponent<GravityControl>();
c.Set(val);
}
/// <summary>
/// 获取物体的重力加速度
/// </summary>
public static Vector3 GetGravity(this GameObject obj)
{
var c = obj.GetComponent<GravityControl>();
if (c == null)
return Physics.gravity;
else
return c.Get();
}
}
/// <summary>
/// 控制单个物体的重力加速度(附加额外的加速度去补正全局设置)
/// </summary>
public class GravityControl : MonoBehaviour
{
private Vector3 _newGravity = Physics.gravity;
private Vector3 _compensate = Vector3.zero;
private Rigidbody _rig;
private void Start()
{
_rig = gameObject.GetComponent<Rigidbody>();
}
public void Set(Vector3 val)
{
if (_newGravity == val)
return;
_newGravity = val;
_compensate = -(Physics.gravity - val);
}
public Vector3 Get() { return _newGravity; }
private void FixedUpdate()
{
if (!_rig.isKinematic && !_rig.IsSleeping() && _compensate!=Vector3.zero)
{
_rig.AddForce(_compensate, ForceMode.Acceleration);
}
}
}
测试代码如下,新建一个场景找个物体把脚本拖上去就好了:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestGravityControl : MonoBehaviour {
// Use this for initialization
IEnumerator Start ()
{
//
var lit = GameObject.Find("Directional Light");
if(lit)
lit.GetComponent<Light>().intensity = 0.5f;
//
Camera.main.transform.position = new Vector3(0, 10, -10);
Camera.main.transform.eulerAngles = new Vector3(20, 0, 0);
//
var p = GameObject.CreatePrimitive(PrimitiveType.Plane);
p.transform.position = Vector3.zero;
p.transform.eulerAngles = Vector3.zero;
p.transform.localScale = new Vector3(10, 1, 10);
p.GetComponent<Renderer>().material.color = Color.black;
// 众所周知,理想状态下物体下落速度只与重力有关,与质量无关
//
var normalG = GameObject.CreatePrimitive(PrimitiveType.Cube);
var nTObj = new GameObject("Text");
var nText = nTObj.AddComponent<TextMesh>();
nText.characterSize = 0.2f;
nText.text = "正常重力";
nText.anchor = TextAnchor.MiddleCenter;
nText.transform.parent = normalG.transform;
nText.transform.position = new Vector3(0, 0.8f, 0);
//
var smallerG = GameObject.CreatePrimitive(PrimitiveType.Cube);
var sTObj = new GameObject("Text");
var sText = sTObj.AddComponent<TextMesh>();
sText.characterSize = 0.2f;
sText.text = "0.5倍重力";
sText.anchor = TextAnchor.MiddleCenter;
sText.transform.parent = smallerG.transform;
sText.transform.position = new Vector3(0, 0.8f, 0);
//
var biggerG = GameObject.CreatePrimitive(PrimitiveType.Cube);
var bTObj = new GameObject("Text");
var bText = bTObj.AddComponent<TextMesh>();
bText.characterSize = 0.2f;
bText.text = "2倍重力";
bText.anchor = TextAnchor.MiddleCenter;
bText.transform.parent = biggerG.transform;
bText.transform.position = new Vector3(0,0.8f,0);
//
var leftDownG = GameObject.CreatePrimitive(PrimitiveType.Cube);
var ldTObj = new GameObject("Text");
var ldText = ldTObj.AddComponent<TextMesh>();
ldText.characterSize = 0.2f;
ldText.text = "偏向左下的0.5倍重力";
ldText.anchor = TextAnchor.MiddleCenter;
ldText.transform.parent = leftDownG.transform;
ldText.transform.position = new Vector3(0, 0.8f, 0);
//
var rightUpG = GameObject.CreatePrimitive(PrimitiveType.Cube);
var ruTObj = new GameObject("Text");
var ruText = ruTObj.AddComponent<TextMesh>();
ruText.characterSize = 0.2f;
ruText.text = "偏向右上的0.1倍重力";
ruText.anchor = TextAnchor.MiddleCenter;
ruText.transform.parent = rightUpG.transform;
ruText.transform.position = new Vector3(0, 0.8f, 0);
//
normalG.transform.position = new Vector3(-2, 10, 0);
smallerG.transform.position = new Vector3(0, 10, 0);
biggerG.transform.position = new Vector3(2, 10, 0);
leftDownG.transform.position = new Vector3(4, 10, 0);
rightUpG.transform.position = new Vector3(-4, 0.5f, 0);
//
yield return new WaitForSeconds(1);
//
normalG.AddComponent<Rigidbody>();
smallerG.AddComponent<Rigidbody>();
biggerG.AddComponent<Rigidbody>();
leftDownG.AddComponent<Rigidbody>();
rightUpG.AddComponent<Rigidbody>();
// 设置重力
smallerG.SetGravity(Physics.gravity * 0.5f);
biggerG.SetGravity(Physics.gravity * 2f);
leftDownG.SetGravity(Matrix4x4.Rotate(Quaternion.Euler(0,0,-45)) * Physics.gravity * 0.5f);
rightUpG.SetGravity(Matrix4x4.Rotate(Quaternion.Euler(0, 0, 135)) * Physics.gravity * 0.1f);
}
}