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

相关推荐
不伤欣7 小时前
游戏设计模式 - 子类沙箱
游戏·unity·设计模式
Magnum Lehar9 小时前
vulkan游戏引擎test文件memory实现
游戏引擎
Magnum Lehar9 小时前
vulkan游戏引擎test_manager实现
java·算法·游戏引擎
快乐觉主吖13 小时前
Unity的日志管理类
android·unity·游戏引擎
WarPigs21 小时前
Unity性能优化笔记
笔记·unity·游戏引擎
T.D.C1 天前
【业务框架】3C-相机-Cinemachine
unity
一线灵1 天前
跨平台游戏引擎 Axmol-2.6.1 发布
游戏引擎
Clank的游戏栈2 天前
Unity基于GraphView的可视化关卡编辑器开发指南
unity·编辑器·游戏引擎
海尔辛2 天前
Unity UI 性能优化--Sprite 篇
ui·unity·性能优化
三巧2 天前
Godot 敌人生成半径和围墙不匹配,导致敌人错误的生成在围墙外的解决代码
游戏引擎·godot