Unity 真实物理动力学实时计算
来源:互联网 发布:佳能wifi软件app 编辑:程序博客网 时间:2024/06/11 22:26
独立开发也很多很多年头了.一直被身边的朋友吐槽我什么都不说
在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 真实物理动力学实时计算
- 物理模拟---动力学模拟
- iOS7 物理动力学UIDynamic
- Unity骨骼动力学应用
- Unity骨骼动力学应用
- UIKit动力学-物理特性UIDynamicItemBehavior
- UIKit动力学-物理特性UIDynamicItemBehavior
- UIKit动力学-物理特性UIDynamicItemBehavior
- Unity LineRender画线+计算空间距离+实时更新数据
- 真实实时皮肤渲染
- [unity教程]游戏的物理和数学:Unity中的弹道和移动目标提前量计算
- 实时物理模拟
- Unity 物理系统--物理材质
- 像素真实的物理长度
- 实时计算
- 实时计算
- Unity 物理属性
- Unity 物理碰撞检测
- 这20个正则表达式,让你少写1,000行代码
- c中角度和弧度的转换
- BZOJ 1045 [HAOI2008] 糖果传递
- 第十一周项目1-验证二叉树算法(1)
- 第一次体验,也是学习也是锻炼!
- Unity 真实物理动力学实时计算
- bzoj1051 [HAOI2006]受欢迎的牛[图论][tarjan缩点]
- SpringMVC环境搭建问题:org.springframework.web.servlet.DispatcherServlet noHandlerFound
- iOS 判断网络连接状态的几种方法
- Android StringUtils-字符串相关工具类
- 最长回文子串
- BZOJ 2763 [JLOI2011]飞行路线
- SIFT和surf
- JQuery Date时间操作