zoukankan      html  css  js  c++  java
  • 体素爆炸

    基本思路:
        离线把怪物死亡那帧的模型数据生成体素信息保存起来
        在死亡的时候,隐藏原本的模型,用体素数据生成体素
        低端机型用特效数据做爆炸,高端机型用真实物理
        体素数量可以在生成时调整(低画质之初20分之一的体素)

    结果:
        看不太出来是从模型样式开始爆炸的,最后使用了纯特效实现

    演示效果图

    体素生成代码使用地图体素信息导出工具临时改的,最终没有用这个方案就没有细化

    爆炸测试脚本记录
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Bomb : MonoBehaviour
    {
    	public bool autoBomb = false;
    	public int cullPower = 0;
    	public float showVoxelTime = 0.1f;
    	public GameObject modelObj;
    	public Transform voxelParent;
    	public ParticleSystem bombPs;
    	public bool usePhysics = false;
    	public float forcePower = 10;
    	public GameObject[] voxelObj;
    
    	float delTime;
    	float showTime;
    	float bombTime;
    	bool isShow;
    	bool isBomb;
    	bool isDoUsePhysics;
    	ParticleSystem.Particle[] m_Particles;
    	List<Vector3> oriPosition;
    
    	// Use this for initialization
    	void Awake()
    	{
    		if (autoBomb)
    		{
    			showTime = Time.time + 1;
    			bombTime = showTime + showVoxelTime;
    			isShow = false;
    			isBomb = false;
    			isDoUsePhysics = false;
    		}
    
    		voxelParent.gameObject.SetActive(false);
    		bombPs.gameObject.SetActive(false);
    
    		oriPosition = new List<Vector3>();
    
    		//剔除
    		if (cullPower > 1)
    		{
    			int nextCull = 0;
    			for (int i = voxelParent.childCount -1; i >= 0; --i)
    			{
    				if (nextCull != 0)
    				{
    					DestroyImmediate(voxelParent.GetChild(i).gameObject);
    				}
    				nextCull = (++nextCull) % cullPower;
    			}
    		}
    
    		//体素生成
    		if (voxelObj != null && voxelObj.Length > 0)
    		{
    			for (int i = 0; i < voxelParent.childCount; ++i)
    			{
    				Transform vox = voxelParent.GetChild(i);
    				GameObject randomVox = voxelObj[Random.Range(0, voxelObj.Length)];
    				GameObject voxObj = Instantiate(randomVox);
    				if (!usePhysics)
    				{
    					Destroy(voxObj.GetComponent<BoxCollider>());
    					Destroy(voxObj.GetComponent<Rigidbody>());
    				}
    
    				voxObj.transform.parent = vox;
    				voxObj.transform.localPosition = Vector3.zero;
    				voxObj.transform.localScale = Vector3.one;
    			}
    		}
    	}
    
    	// Update is called once per frame
    	void Update()
    	{
    		if (!autoBomb)
    			return;
    
    		if (!isShow)
    		{
    			if (Time.time >= showTime)
    			{
    				delTime = Time.time + 3;
    				isShow = true;
    				if (modelObj != null) modelObj.SetActive(false);
    				voxelParent.gameObject.SetActive(true);
    
    				for (int i = 0; i < voxelParent.childCount; ++i)
    				{
    					Transform vox = voxelParent.GetChild(i);
    					oriPosition.Add(vox.position);
    				}
    			}
    			else
    			{
    				return;
    			}
    		}
    
    		if (Time.time >= delTime)
    		{
    			Destroy(gameObject);
    		}
    
    		if (Time.time < bombTime)
    			return;
    
    		if (!isBomb)
    		{
    			isBomb = true;
    
    			short nVoxelCount = (short)voxelParent.childCount;
    			m_Particles = new ParticleSystem.Particle[nVoxelCount];
    			bombPs.emission.SetBursts(new ParticleSystem.Burst[] { new ParticleSystem.Burst(0.0f, nVoxelCount, nVoxelCount) });
    			bombPs.gameObject.SetActive(true);
    			return;
    		}
    
    		if (!usePhysics)
    		{
    			Quaternion qua = bombPs.transform.rotation;
    			int numParticlesAlive = bombPs.GetParticles(m_Particles);
    			for (int i = 0; i < voxelParent.childCount; ++i)
    			{
    				if (i >= numParticlesAlive)
    					return;
    
    				Transform newTrans = voxelParent.GetChild(i);
    				newTrans.forward = qua * m_Particles[i].rotation3D;
    				newTrans.position = oriPosition[i] + qua * m_Particles[i].position;
    			}
    		}
    		else
    		{
    			if (!isDoUsePhysics)
    			{
    				isDoUsePhysics = true;
    				Quaternion qua = bombPs.transform.rotation;
    				int numParticlesAlive = bombPs.GetParticles(m_Particles);
    				for (int i = 0; i < voxelParent.childCount; ++i)
    				{
    					if (i >= numParticlesAlive)
    						return;
    
    					Vector3 force = qua * m_Particles[i].velocity;
    					force *= forcePower;
    
    					Transform newTrans = voxelParent.GetChild(i);
    					var rigi = newTrans.GetComponentInChildren<Rigidbody>();
    					rigi.AddForce(force);
    				}
    
    				bombPs.gameObject.SetActive(false);
    			}
    		}
    	}
    
    	[ContextMenu("DoBomb")]
    	public void DoBomb()
    	{
    		autoBomb = true;
    		showTime = Time.time;
    		bombTime = showTime + showVoxelTime;
    	}
    
    	[ContextMenu("DelAllRender")]
    	public void DelAllRender()
    	{
    		for (int i = 0; i < voxelParent.childCount; ++i)
    		{
    			GameObject obj = voxelParent.GetChild(i).gameObject;
    			DestroyImmediate(obj.GetComponent<MeshFilter>());
    			DestroyImmediate(obj.GetComponent<MeshRenderer>());
    		}
    	}
    }
    





  • 相关阅读:
    LeetCode 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/Hichy/p/8033783.html
Copyright © 2011-2022 走看看