使用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

相关推荐
DaLiangChen9 小时前
Unity 精准 Mesh 点击检测:穿透遮挡 + 单击双击识别
unity·游戏引擎
迪普阳光开朗很健康12 小时前
Unity中new() 和实例化有什么区别?
unity·游戏引擎
mxwin12 小时前
Unity Shader 极坐标特效 从数学原理到实战案例
unity·游戏引擎·shader·uv
魔士于安1 天前
unity 圆盘式 太空飞船
游戏·unity·游戏引擎·贴图·模型
陈言必行1 天前
Unity 之 Addressables 加载失败:路径变量未替换导致的 404 错误分析与解决
unity·游戏引擎
qq_170264752 天前
unity出安卓年龄分级的arr包问题
android·unity·游戏引擎
WMX10122 天前
Holoens2开发报错记录02_unity项目常见错误
unity
魔士于安2 天前
宇宙版地球模拟器
游戏·unity·游戏引擎·贴图·模型
魔士于安2 天前
氛围感游戏场景,天空盒,带地形,附赠一个空要塞
游戏·unity·游戏引擎·贴图
ellis19702 天前
Unity程序集(assembly)笔记
unity