1. 程式人生 > >Unity 真實物理動力學實時計算

Unity 真實物理動力學實時計算

獨立開發也很多很多年頭了.一直被身邊的朋友吐槽我什麼都不說
在csdn也有幾個年頭了.
最近又被一些國外友人吐槽我. 稀字如金
所信就借這個部落格寫點東西吧.哈哈這個也算是我人生的第一篇博文啊
好了.廢話不表,進入正題.

===================我是分割線===================

這個想法最初來源於我為了實現遊戲Claidia中的各種飄動擺動效果.但是由於Unity原生的似乎達不到我想要的那種可以隨意控制.調整張力.重力.以及其他係數的功能.
所以一直在想說能不能通過DX11來實現.但是那樣似乎效率上有些問題.流暢度可能達不到一個遊戲的執行標準.畢竟一個大型MMO單幀畫面渲染全屏使用者至少要保證100個動態單位吧.
所以對效率還是有一定要求的.因此在為了保證效率和質量的情況下.一次玩某款日本的遊戲的時候從中得到靈感.
下面上程式碼
整套動力系統模擬由一個主管理類和每個分節點受力計算類控制
首先主管理類:
PhysicalDynamicsSystem.cs

using UnityEngine;
using System.Collections.Generic;

namespace DIYPhySys
{
    public class PhysicalDynamicsSystem : MonoBehaviour
    {
        static PhysicalDynamicsSystem PDManager;
        public float dynamicRatio = 1.0f;
        public Transform Bip;

        public float            stiffnessForce;
        public
AnimationCurve stiffnessCurve; public float dragForce; public AnimationCurve dragCurve; public List<DynamicsBone> dynamicsBones = new List<DynamicsBone>(); public bool SetOnce; public bool AllTest; void Awake(){PDManager = this
;} public static PhysicalDynamicsSystem GetSpmm() { return PDManager; } void Start () { dynamicsBones.Clear(); DynamicsBone[] dbs = Bip.GetComponentsInChildren<DynamicsBone>(); for (int i = 0; i < dbs.Length; i ++) { if (AllTest) { dbs[i].stiffnessForce = stiffnessForce; dbs[i].dragForce = dragForce; } if (dbs[i].child) dynamicsBones.Add(dbs[i]); } GetComponent<RandomWind>().IntStart(this); UpdateParameters (); } void Set() { if(SetOnce) { SetOnce = false; foreach (DynamicsBone db in dynamicsBones) { db.stiffnessForce = stiffnessForce; db.dragForce = dragForce; } } } void Update () { Set(); #if UNITY_EDITOR if (dynamicRatio >= 1.0f) dynamicRatio = 1.0f; else if(dynamicRatio <= 0.0f) dynamicRatio = 0.0f; UpdateParameters(); #endif } private void LateUpdate () { if (dynamicRatio != 0.0f) { for (int i = 0; i < dynamicsBones.Count; i++) { if (dynamicRatio > dynamicsBones [i].threshold) { dynamicsBones [i].UpdateSpring (); } } } } private void UpdateParameters () { UpdateParameter ("stiffnessForce", stiffnessForce, stiffnessCurve); UpdateParameter ("dragForce", dragForce, dragCurve); } private void UpdateParameter (string fieldName, float baseValue, AnimationCurve curve) { var start = curve.keys [0].time; var end = curve.keys [curve.length - 1].time; //var step = (end - start) / (springBones.Length - 1); var prop = dynamicsBones [0].GetType ().GetField (fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); for (int i = 0; i < dynamicsBones.Count; i++) { if (!dynamicsBones [i].isUseEachBoneForceSettings) { var scale = curve.Evaluate (start + (end - start) * i / (dynamicsBones.Count - 1)); prop.SetValue (dynamicsBones [i], baseValue * scale); } } } } }

其次分節點編輯器模式下的視覺化幫助:
DynamicsCollider.cs

using UnityEngine;
using System.Collections;

namespace DIYPhySys
{
    public class DynamicsCollider : MonoBehaviour
    {
        //半徑
        public float radius = 0.5f;

        private void OnDrawGizmosSelected ()
        {
            Gizmos.color = Color.green;
            Gizmos.DrawWireSphere (transform.position, radius);
        }
    }
}

最後每個分節點真實物理動力學受力和力反饋類:

DynamicsBone.cs

using UnityEngine;
using System.Collections.Generic;

namespace DIYPhySys
{
    public class DynamicsBone : MonoBehaviour
    {
        public Transform child;
        public Vector3 boneAxis = new Vector3 (-1.0f, 0.0f, 0.0f);
        public float radius = 0.05f;
        public bool isUseEachBoneForceSettings = false; 
        public float stiffnessForce = 0.01f;
        public float dragForce = 0.4f;
        public Vector3 springForce = new Vector3 (0.0f, -0.0001f, 0.0f);
            public List<DynamicsCollider> colliders = new List<DynamicsCollider>();
        public bool debug = true;
        public float threshold = 0.01f;
        private float springLength;
        private Quaternion localRotation;
        private Transform trs;
        private Vector3 currTipPos;
        private Vector3 prevTipPos;
        private Transform org;
        private PhysicalDynamicsSystem managerRef;

        private void Awake ()
        {
            if (child)
            {
                trs = transform;
                localRotation = transform.localRotation;
                managerRef = GetParentSpringManager(transform);
            }
        }

        private PhysicalDynamicsSystem GetParentSpringManager (Transform t)
        {
            var springManager = t.GetComponent<PhysicalDynamicsSystem> ();

            if (springManager != null)
                return springManager;

            if (t.parent != null) {
                return GetParentSpringManager (t.parent);
            }

            return null;
        }

        private void Start ()
        {
            if (child)
            {
                springLength = Vector3.Distance(trs.position, child.position);
                currTipPos = child.position;
                prevTipPos = child.position;
            }
        }

        public void UpdateSpring ()
        {
            org = trs;
            trs.localRotation = Quaternion.identity * localRotation;

            float sqrDt = Time.deltaTime * Time.deltaTime;
            Vector3 force = trs.rotation * (boneAxis * stiffnessForce) / sqrDt;
            force += (prevTipPos - currTipPos) * dragForce / sqrDt;
            force += springForce / sqrDt;
            Vector3 temp = currTipPos;
            currTipPos = (currTipPos - prevTipPos) + currTipPos + (force * sqrDt);
            currTipPos = ((currTipPos - trs.position).normalized * springLength) + trs.position;
            for (int i = 0; i < colliders.Count; i++) {
                if (Vector3.Distance (currTipPos, colliders [i].transform.position) <= (radius + colliders [i].radius)) {
                    Vector3 normal = (currTipPos - colliders [i].transform.position).normalized;
                    currTipPos = colliders [i].transform.position + (normal * (radius + colliders [i].radius));
                    currTipPos = ((currTipPos - trs.position).normalized * springLength) + trs.position;
                }


            }

            prevTipPos = temp;
            Vector3 aimVector = trs.TransformDirection (boneAxis);
            Quaternion aimRotation = Quaternion.FromToRotation (aimVector, currTipPos - trs.position);
            Quaternion secondaryRotation = aimRotation * trs.rotation;
            trs.rotation = Quaternion.Lerp (org.rotation, secondaryRotation, managerRef.dynamicRatio);
        }

        private void OnDrawGizmos ()
        {
            if (debug) {
                Gizmos.color = Color.yellow;
                Gizmos.DrawWireSphere (currTipPos, radius);
            }
        }
    }
}

到此全部程式碼貼出

大家根據自己需要靈活運用就可以得到想要的真實物理模擬反饋啦
主要注意的是 主管理類 請繫結到骨骼根節點哦.其次這個模擬是根據骨骼節點數量來執行的
主節點統一對根節點進行力傳遞.然後跟節點根據各自的特性係數進行不同的力衰減力回饋還有力傳導的計算模擬.
感謝大家閱讀了.
以後我會有時間有心情了在和大家分享一些有價值的東西
^_^
[轉載請註明作者和出處]
====================我是分割線====================

相關推薦

Unity 真實物理動力學實時計算

獨立開發也很多很多年頭了.一直被身邊的朋友吐槽我什麼都不說 在csdn也有幾個年頭了. 最近又被一些國外友人吐槽我. 稀字如金 所信就借這個部落格寫點東西吧.哈哈這個也算是我人生的第一篇博文啊 好了.廢話不表,進入正題. ===============

一臉懵逼學習Storm---(一個開源的分布式實時計算系統)

在線 協調 深入 tor grouping 分配 有一點 cbo con 1:什麽是Storm?  Storm是一個開源的分布式實時計算系統,可以簡單、可靠的處理大量的數據流。被稱作“實時的hadoop”。Storm有很多使用場景:如實時分析,在線機

Flink+kafka實現Wordcount實時計算

lis AS -c 安裝包 pos localhost 行動 private 配置信息 1. Flink Flink介紹: Flink 是一個針對流數據和批數據的分布式處理引擎。它主要是由 Java 代碼實現。目前主要還是依靠開源社區的貢獻而發展。對 Flink 而言,其所

ARMS: 原來實時計算可以這麽簡單!

數據收集 發現 groupby lec 分享 選擇 tab ces ref 摘要: 業務實時監控服務( ARMS)是一款阿裏雲應用性能管理(APM)類監控產品。借助本產品,您可以基於前端、應用、業務自定義等服務,迅速便捷地為企業構建秒級響應的業務監控能力。業務實時監控服務(

如何實現最佳的跨平臺遊戲體驗?Unity成亮解密實時渲染技術!

批次 實現 中心 目的 同時 應用軟件安裝 例子 發的 不同的 7月31日,2018雲創大會遊戲論壇在杭州國際博覽中心103B圓滿舉行。本場遊戲論壇聚焦探討了可能對遊戲行業發展有重大推動的新技術、新實踐,如AR、區塊鏈、安全、大數據等。Unity大中華區技術經理成亮表示,實

100億小數據實時計算平臺

style 至少 關系 秒殺 java 大數據分析 找到 實例 data 2017年6月,開始數據分析的職業生涯,作為架構師,建立起一套基於.Net/.Net Core的小數據實時處理計算平臺,這裏記錄學習過程中的點點滴滴! 數據分析的核心,可以理解為:Select xx

CSS中盒子模型的真實寬高怎麼計算

盒子一共有四個屬性:分別為外邊距(margin)、邊框(border)、內邊距(padding)、內容(content). 關係如下圖所示: 而我們平常設定盒子的寬和高往往是指的內容的寬和高 div{ width:200px; height:18px; }

【號外】實時計算徵集使用者案例,看看誰是實時計算幸運錦鯉!

阿里雲 實時計算今年4月份正式商業化之後,短短2個月,已增加100+付費使用者。截止目前,使用使用者已經超過2000家。在已有的使用者中,實時計算主要應用於實時網際網路資料分析、實時資料大屏、實時金融風控、電商實時推薦等諸多領域。阿里集團內淘寶、天貓、天弘基金、菜鳥、工業大

實時計算 Flink效能調優

自動配置調優 實時計算 Flink新增自動調優功能autoconf。能夠在流作業以及上下游效能達到穩定的前提下,根據您作業的歷史執行狀況,重新分配各運算元資源和併發數,達到優化作業的目的。更多詳細說明請您參閱自動配置調優。 首次智慧調優 建立一個作業。如何建立作業請參看快速入門。 上線作業

機械臂動力學--加速度計算

機械臂動力學–加速度計算 線加速度 在部落格《速度與向量的微分》的式(5-12)描述了座標系{A}下的速度向量 B

雙11之後首秀:阿里雲實時計算究竟對Apache Flink做了哪些‘改造’?

關於實時計算 實時計算LOGO 實時計算(Alibaba Cloud Realtime Compute,原阿里雲流計算)是一套基於Apache Flink™️構建的一站式、高效能實時大資料處理平臺,廣泛適用於流式資料處理、離線資料處理、DataLake計算等多種場景。實時計算主要應用於實時網際網路資料

unity矩陣運算,數學計算

1. 官方文件 Mathf   https://docs.unity3d.com/ScriptReference/Mathf.html Matrix4x4 https://docs.unity3d.com/ScriptReference/Matrix4x4.ht

Hadoop(三) 大資料離線計算實時計算

分享一下我老師大神的人工智慧教程吧。零基礎,通俗易懂!風趣幽默!http://www.captainbed.net/ 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

攜程實時計算平臺架構與實踐丨DataPipeline

文 | 潘國慶 攜程大資料平臺實時計算平臺負責人 本文主要從攜程大資料平臺概況、架構設計及實現、在實現當中踩坑及填坑的過程、實時計算領域詳細的應用場景,以及未來規劃五個方面闡述攜程實時計算平臺架構與實踐,希望對需要構建實時資料平臺的公司和同學有所借鑑。 一、攜程大資料平臺之總體架構 攜程

阿里雲實時計算的前世“功”今生“能”

前言:不修內功,難成大器。為了將Apache Flink在阿里巴巴真正執行起來,阿里巴巴實時計算團隊做了大量的優化,在阿里雲上的產品正式命名為實時計算,以Flink SQL為主要API,致力於打造一款全球領先的實時計算引擎。 正文:阿里雲實時計算大可成稻草,小亦是利器在光明日報近期的文章中,回首網際網路接入

阿裏雲實時計算的前世“功”今生“能”

支持 計算引擎 陜西 增長 進行 穩定性 批處理 申請 相同 前言:不修內功,難成大器。為了將Apache Flink在阿裏巴巴真正運行起來,阿裏巴巴實時計算團隊做了大量的優化,在阿裏雲上的產品正式命名為實時計算,以Flink SQL為主要API,致力於打造一款全球領先的實

阿里雲實時計算,前世功,今生能!

前言: 不修內功,難成大器。為了將Apache Flink在阿里巴巴真正執行起來,阿里巴巴實時計算團隊做了大量的優化,在阿里雲上的產品正式命名為實時計算,以Flink SQL為主要API,致力於打造一款全球領先的實時計算引擎。 正文: 阿里雲實時計算大可成稻草,小亦是利器 在光明日報近期

unity純粹物理驅動方式

首先見官方文件 In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour. Don't set the velocity of an object every

[Flink基礎]-- 與其他實時計算框架對比

對比其他計算框架 Spark Storm Flink Streaming Model Micro-batch Native Native

滴滴是如何從零構建集中式實時計算平臺的?| 技術頭條

作者 | 樑李印 責編 | 唐小引 出品 | CSDN(ID:CSDNNews) 滴滴出行作為一家出行領域的網際網路公司,其核心業務是一個實時線上服務。因此具有豐富的實時資料和實時計算場景。本文將介紹滴滴實時計算髮展之路以及平臺架構實踐。 實時計算