前几天看了一篇体素渲染技术的文章,就突然想起这个挖了很久的坑……
话说不管是像素化风格还是体素化风格都好可爱啊!
感觉像在玩我的世界。
之前写的时候也没细想,用的简单粗暴的蠢方法,性能耗的一批又有诸多限制。
原理很是简单粗暴,把原物体加上collider和刚体,然后在它的bounds里生成指定大小的cube,然后原物体上绑上触发检测的脚本,如果碰到了cube,就修改cube的tag为“cube”,最后把tag为“cube”的cube网格合并,再把cube全都destroy掉,把生成的网格存下来就行啦。
现在看看简直蠢爆了哈哈哈哈哈,下次试试用shader做做看,等我把那坨屎一样的游戏代码写完……
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class TiSuHua : MonoBehaviour
{
public GameObject prefab;
public Material material;
private Transform newGo;
private Bounds bounds;
[Range(0.2f, 1.0f)]
public float cubeSize = 0.5f;
private MeshFilter[] cubeMeshs;
private void CreateTiSu()
{
int widthCubeCount = (int)(bounds.size.x / cubeSize + 1);
int lengthCubeCount = (int)(bounds.size.z / cubeSize + 1);
int heightCubeCount = (int)(bounds.size.y / cubeSize + 1);
float cubePositionX = bounds.center.x - cubeSize * widthCubeCount / 2 + cubeSize / 2;
float cubePositionY = bounds.center.y - cubeSize * heightCubeCount / 2 + cubeSize / 2;
float cubePositionZ = bounds.center.z - cubeSize * lengthCubeCount / 2 + cubeSize / 2;
for (int i = 0; i < heightCubeCount; i++)
{
for (int j = 0; j < lengthCubeCount; j++)
{
for (int k = 0; k < widthCubeCount; k++)
{
Vector3 position = new Vector3(cubePositionX, cubePositionY, cubePositionZ);
cubePositionX += cubeSize;
CreateCube(position);
}
cubePositionZ += cubeSize;
cubePositionX = bounds.center.x - cubeSize * widthCubeCount / 2 + cubeSize / 2;
}
cubePositionY += cubeSize;
cubePositionX = bounds.center.x - cubeSize * widthCubeCount / 2 + cubeSize / 2;
cubePositionZ = bounds.center.z - cubeSize * lengthCubeCount / 2 + cubeSize / 2;
}
}
private void CreateCube(Vector3 position)
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = position;
cube.transform.localScale = new Vector3(cubeSize, cubeSize, cubeSize);
cube.GetComponent<BoxCollider>().isTrigger = true;
cube.transform.parent = newGo;
}
void Start()
{
GameObject go = Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;
bounds = go.GetComponent<Renderer>().bounds;
go.AddComponent<Rigidbody>();
go.GetComponent<Rigidbody>().isKinematic = true;
go.AddComponent<CollisionTest>();
newGo = new GameObject("newGo").transform;
newGo.gameObject.AddComponent<MeshFilter>();
newGo.gameObject.AddComponent<MeshRenderer>();
CreateTiSu();
cubeMeshs = newGo.GetComponentsInChildren<MeshFilter>();
Destroy(go);
}
private bool alreadyCombineCube = false;
private void LateUpdate()
{
if (!alreadyCombineCube)
{
List<CombineInstance> combines = new List<CombineInstance>();
for (int i = 0; i < cubeMeshs.Length; i++)
{
if (cubeMeshs[i].tag == "cube")
{
combines.Add(new CombineInstance()
{
mesh = cubeMeshs[i].sharedMesh,
transform = cubeMeshs[i].transform.localToWorldMatrix
});
}
cubeMeshs[i].transform.parent = null;
Destroy(cubeMeshs[i].gameObject);
}
CombineInstance[] cb = combines.ToArray();
newGo.GetComponent<MeshFilter>().mesh.CombineMeshes(cb);
newGo.GetComponent<MeshRenderer>().material = material;
AssetDatabase.CreateAsset(newGo.GetComponent<MeshFilter>().mesh, "Assets/" + prefab.name + "VoxelMesh.asset");
PrefabUtility.CreatePrefab("Assets/" + prefab.name + "Voxel.prefab", newGo.gameObject);
AssetDatabase.SaveAssets();
Instantiate(newGo.gameObject,prefab.transform.position,Quaternion.identity);
}
alreadyCombineCube = true;
}
}