C#实现的Unity集群系统编辑器正常 Android AR打包后粒子随机飞散
Unity Flocking集群系统Android AR构建运行异常求助
问题描述
基于两份C#脚本实现flocking集群效果:通过自定义逻辑控制集群对象周期性切换追踪目标、停止追踪目标状态,最终呈现类似呼吸的集群内外收放动态效果。
- 运行表现差异:
- Unity编辑器内运行:效果完全符合预期
- 打包为Android平台AR应用后:粒子在前5-10秒可正常遵循脚本逻辑运动,之后会完全脱离控制随机飞散
- 已排除诱因:有推测认为异常由AR Session Origin组件工作异常导致,但测试验证无论是否配置Image Target,异常都会稳定触发
- 目前构建目标平台为Android,寻求有同类问题排查经验的开发者提供排查方向参考
- 效果参考视频:
相关脚本代码
FlockManager.cs
using System.Collections.Generic; using UnityEngine; public class FlockManager : MonoBehaviour { // 集群粒子对象列表 public List<GameObject> particles; public GameObject particlePrefab; public Vector3 range = new Vector3(2,2,2); public Material[] mats; public bool seekGoal = true; public bool obedient = true; public bool willful = false; [Range(0, 200)] public int neighbourDistance =50; [Range(0,2)] public float maxForce = 1.0f; [Range(0,5)] public float maxvelocity = 2.0f; // 集群粒子数量动态变化数据集 public int[] dataSet = new int[] {128, 135, 151, 168, 187, 206, 229, 253, 279, 307, 338, 371, 407, 446, 487, 533}; int dataIndex = 0; void Start() { generateParticles(128); willful = false; // 每5秒切换一次追踪/自由状态 InvokeRepeating("toggleSeek", 0f, 5f); // 每10秒调整一次集群粒子数量 InvokeRepeating("setParticleNumbers", 0f, 10f); } void setParticleNumbers() { if(dataIndex == dataSet.Length) { dataIndex = 0; } generateParticles(dataSet[dataIndex]); dataIndex = dataIndex + 1; } void toggleSeek() { seekGoal = !seekGoal; obedient = !obedient; willful = !willful; } void generateParticles(int numberOfParticles) { var difference = numberOfParticles - particles.Count; if(difference >= 0) { for(int i = 0; i < difference; i++) { addParticle(); } } else { for(int i = 0; i < difference * -1; i++) { // 销毁场景中多余粒子 Destroy(particles[particles.Count - 1]); // 从列表中移除对应粒子引用 particles.RemoveAt(particles.Count - 1); } } } void addParticle() { Vector3 particlePos = new Vector3(Random.Range(-range.x, range.x), Random.Range(-range.y, range.y), Random.Range(-range.z, range.z)); var GO = Instantiate(particlePrefab, this.transform.position + particlePos, Quaternion.identity) as GameObject; GO.GetComponent<FlockParticleBehaviour>().manager = this.gameObject; particles.Add(GO); GO.GetComponent<Renderer>().material = mats[Random.Range(0,mats.Length)]; } }
FlockParticleBehaviour.cs
using System.Collections.Generic; using UnityEngine; public class FlockParticleBehaviour : MonoBehaviour { public GameObject manager; public Vector3 location = Vector3.zero; public Vector3 velocity; Vector3 goalPos = Vector3.zero; Vector3 currentForce; void Start() { velocity = new Vector3(Random.Range(0.01f, 0.1f), Random.Range(0.01f, 0.1f), Random.Range(0.01f, 0.1f)); location = new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y, this.gameObject.transform.position.z); } // 指向目标位置的引导向量 Vector3 seek(Vector3 target) { return(target - location); } void applyForce(Vector3 f) { Vector3 force = new Vector3(f.x, f.y, f.z); if(force.magnitude > manager.GetComponent<FlockManager>().maxForce) { force = force.normalized; force *= manager.GetComponent<FlockManager>().maxForce; } this.GetComponent<Rigidbody>().AddForce(force); if(this.GetComponent<Rigidbody>().velocity.magnitude > manager.GetComponent<FlockManager>().maxvelocity) { this.GetComponent<Rigidbody>().velocity = this.GetComponent<Rigidbody>().velocity.normalized; this.GetComponent<Rigidbody>().velocity *= manager.GetComponent<FlockManager>().maxvelocity; } Debug.DrawRay(this.transform.position, force, Color.white); } // 对齐规则:匹配邻域粒子平均速度 Vector3 align() { float neighbourdist = manager.GetComponent<FlockManager>().neighbourDistance; Vector3 sum = Vector3.zero; int count = 0; foreach (GameObject other in manager.GetComponent<FlockManager>().particles) { if(other == this.gameObject) continue; float d = Vector3.Distance(location, other.GetComponent<FlockParticleBehaviour>().location); if (d < neighbourdist) { sum += other.GetComponent<FlockParticleBehaviour>().velocity; count++; } } if (count >0) { sum /= count; Vector3 steer = sum - velocity; return steer; } return Vector3.zero; } // 聚合规则:向邻域粒子平均位置移动 Vector3 cohesion() { float neighbourdist = manager.GetComponent<FlockManager>().neighbourDistance; Vector3 sum = Vector3.zero; int count = 0; foreach (GameObject other in manager.GetComponent<FlockManager>().particles) { if(other == this.gameObject) continue; float d = Vector3.Distance(location, other.GetComponent<FlockParticleBehaviour>().location); if(d < neighbourdist) { sum += other.GetComponent<FlockParticleBehaviour>().location; count++; } } if (count > 0) { sum /= count; return seek(sum); } return Vector3.zero; } void flock() { location = this.transform.position; velocity = this.GetComponent<Rigidbody>().velocity; if(manager.GetComponent<FlockManager>().obedient && Random.Range(0,50) <=1) { Vector3 ali = align(); Vector3 coh = cohesion(); Vector3 gl; if(manager.GetComponent<FlockManager>().seekGoal) { gl = seek(goalPos); currentForce = gl + ali +coh; } else currentForce = ali + coh; currentForce = currentForce.normalized; } if(manager.GetComponent<FlockManager>().willful && Random.Range(0,50)<=1) { if(Random.Range(0,50)<1) // 随机改变运动方向 currentForce = new Vector3(Random.Range(0.01f, 0.1f), Random.Range(0.01f, 0.1f),Random.Range(0.01f, 0.1f)); } applyForce(currentForce); } void Update() { flock(); goalPos = manager.transform.position; } }
内容的提问来源于stack exchange,提问作者Delayne Rutter
相关产品推荐
相关产品推荐

