使用Unity脚本模拟绳索、布料(碰撞)

效果演示:

脚本如下:

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PhysicsLab
{
	public class RopeSolver : MonoBehaviour {
		public Transform ParticlePrefab;
		public int Count = 3;
		public int Space = 1;
		[Range(0, 1)]
		public float Damping = 0.1f;
		public Vector3 ExternForce = Vector3.zero;
		public int SolveCount = 1;

		[Header("Collider")]
		public RopeSphereCollider sphereCollider;

		private List<Transform> chain = new List<Transform>();
		private List<Particle> particleList = new List<Particle>();

		void Start()
		{
			for (int i=0; i<Count; i++)
			{
				var obj = Instantiate(ParticlePrefab, transform, true);
				obj.Translate(0, -i * Space, 0);
				chain.Add(obj);

				// Construct Particles
				var particle = new Particle();
				particle.radius = 0.5f * Space;
				particle.pos = particle.prevPos = new Vector3(0, -i * Space, 0);
				particle.velocity = Vector3.zero;
				particleList.Add(particle);
			}
		}

		void FixedUpdate ()
		{
			// Update Velocity
			for (int i=0; i<Count; i++)
			{
				var particle = particleList[i];

				// Verlet Integration
				Vector3 vel = particle.velocity + ExternForce * Time.fixedDeltaTime * Time.fixedDeltaTime;
				particle.prevPos = particle.pos;
				particle.pos = particle.pos + (1-Damping) * vel;
			}

			// Resolve Constraints
			// 1. Attach Root Particle to base transform
			particleList[0].pos = transform.position;

			// 2. Keep Length Constraint from top to bottom
			for (int n=0; n<SolveCount; n++)
			{
				for (int i=1; i<Count; i++)
				{
					Vector3 offsetToParent = particleList[i].pos - particleList[i-1].pos;
					// Strategy 1: only move child particle
					//particleList[i].pos = particleList[i-1].pos + Space * offsetToParent.normalized;
					// Strategy 2: Position Based Dynamics, iteratively
					offsetToParent = Space * offsetToParent.normalized - offsetToParent;
					particleList[i-1].pos -= 0.5f * offsetToParent;
					particleList[i].pos += 0.5f * offsetToParent;
				}

				// Attach Root Particle to base transform
				particleList[0].pos = transform.position;
			}

			// Collision Detection & Response
			if (sphereCollider != null)
			{
				for (int i=0; i<Count; i++)
				{
					sphereCollider.UpdateCollision(particleList[i]);
				}
			}

			// Update velocity
			for (int i=0; i<Count; i++)
			{
				particleList[i].velocity = particleList[i].pos - particleList[i].prevPos;
			}

			// Apply Particle Data to Transform
			for (int i=0; i<Count; i++)
			{
				chain[i].position = particleList[i].pos;
			}
		}
	}

	public class Particle
	{
		public float radius;
		public Vector3 pos;
		public Vector3 prevPos;
		public Vector3 velocity;
	}
}
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PhysicsLab
{
	[RequireComponent(typeof(Transform))]
	public class RopeSphereCollider : MonoBehaviour 
	{
		private Transform sphereTfm;
		
		void OnEnable()
		{
			sphereTfm = GetComponent<Transform>();
		}
		
		public void UpdateCollision(Particle particle)
		{
			Vector3 colliderCenter = sphereTfm.position;
			float colliderR = sphereTfm.lossyScale.x * 0.5f;
			Vector3 offset = particle.pos - colliderCenter;
			if (offset.magnitude < colliderR + particle.radius) // Collision Detected
			{
				// Collision Response
				particle.pos = colliderCenter + offset.normalized * (colliderR + particle.radius);
			}
		}
	}
}

源码下载链接: https://download.csdn.net/download/qq_41603955/90086948

相关推荐
SmalBox1 天前
【光照】[漫反射diffuse]以UnityURP为例
unity·渲染
SmalBox2 天前
【光照】[自发光Emission]以UnityURP为例
unity·渲染
SmalBox3 天前
【光照】Unity中的[经验模型]
unity·渲染
萘柰奈3 天前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
Yasin Chen3 天前
Unity UI坐标说明
ui·unity
应用市场3 天前
无人机姿态控制系统详解与实现
游戏引擎·cocos2d
陈言必行4 天前
Unity 性能优化 之 编辑器创建资源优化( 工作流 | 场景 | 预制体)
unity·编辑器·游戏引擎
1uther4 天前
Unity核心概念⑨:Screen
开发语言·游戏·unity·c#·游戏引擎
死也不注释4 天前
【Unity UGUI 交互组件——Slider(7)】
unity·游戏引擎·交互
程序猿多布4 天前
XLua教程之热补丁技术
unity·c#·lua·xlua