Unity改变单个物体的重力

通过对官方文档查询,可以确定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);
    }
}

 

  • 9
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值