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

相关推荐
Unity大海1 小时前
诠视科技Unity SDK开发环境配置、项目设置、apk打包。
科技·unity·游戏引擎
浅陌sss7 小时前
Unity中 粒子系统使用整理(一)
unity·游戏引擎
维度攻城狮11 小时前
实现在Unity3D中仿真汽车,而且还能使用ros2控制
python·unity·docker·汽车·ros2·rviz2
为你写首诗ge14 小时前
【Unity网络编程知识】FTP学习
网络·unity
神码编程16 小时前
【Unity】 HTFramework框架(六十四)SaveDataRuntime运行时保存组件参数、预制体
unity·编辑器·游戏引擎
菲fay18 小时前
Unity 单例模式写法
unity·单例模式
火一线19 小时前
【Framework-Client系列】UIGenerate介绍
游戏·unity
ZKY_2420 小时前
【工具】Json在线解析工具
unity·json
ZKY_241 天前
【Unity】处理文字显示不全的问题
unity·游戏引擎
快乐非自愿2 天前
Netty源码—10.Netty工具之时间轮
java·unity·.net