unity点选构建Mesh并保存OBJ

这篇博客讲述了如何在Unity中实现策划指定区域选择,通过构建和保存自定义Mesh来满足需求。作者分享了简单shader的编写、脚本控制以及自创Mesh的保存过程,旨在简化后续程序使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近有一份需求,就是让策划任意选择可一片区域,表明是有某种用途的。埋头写了两头,试了三四种方法,最终不得已用小方格来代替,并最终构建mesh保存下来,这样做程序的就很方便用了。我们的目标就是没有蛀牙大笑oh,应该是累死别人,轻松自己!!!

1,简单shader编写

首先应该搞一个简单的Shader来显示我们的所编辑的内容
Shader "Custom/BlockShader" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_Size ("Size",Vector) = (64,32,0,0) //在面板上显示长多少格,宽多少格
		_Color ("Color", Color) = (0,0,0,0.5)
		_RimColor ("Rim Color", Color) = (1,1,0,1)
		_RimPower ("Rim Power", Range(0,0.2)) = 0.01
		_HitPoint ("Hit Point",Vector) = (0.0,1,0.0,0.5)//鼠标点击点
		_SelectColor ("Select Color",Color) = (0,1,0,1)//选中颜色
		_HitColor ("Already hit Color", Color) = (0.2,0.8,0.9,0.5)
	}
	SubShader {
		Tags { "Queue"="Transparent" }
		
		CGPROGRAM
		#pragma surface surf Lambert alpha
		#pragma target 3.0

		sampler2D _MainTex;
		half4 _Size;
		fixed4 _Color;
		fixed4 _RimColor;
		float _RimPower;
		float4 _HitPoint;
		fixed4 _SelectColor;
		fixed4 _HitColor;

		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) {
			float2 uv = IN.uv_MainTex;
			fixed4 c = _Color;
			float radiox = 1.0 / (_Size.x * 2);//每格大小的一半
			float radioy = 1.0 / (_Size.y * 2);

			float nx = floor(uv.x/(radiox * 2)) * radiox * 2 + radiox;//找到格的中心点
			float ny = floor(uv.y/(radioy * 2)) * radioy * 2 + radioy;
			fixed4 tc = tex2D (_MainTex, float2(nx,ny) );
			if(tc.g > 0.85) //因为选中我设置为了绿色(0,1,0,1)
			{
				c = _HitColor;
				//if(uv.x >= nx-radiox && uv.x <nx+ radiox && uv.y >= ny-radioy && uv.y <= ny+radioy)
				//{ 
				//	c = _HitColor;
				//}
			}


			if(uv.x >= _HitPoint.x-radiox && uv.x <_HitPoint.x+ radiox && uv.y >= _HitPoint.y-radioy && uv.y <= _HitPoint.y+radioy)
			{ 
				c = _SelectColor;//选中颜色
			}

			if(fmod(uv.x ,(radiox * 2)) < (radiox * 2) * _RimPower)//边框
			{
				c = _RimColor;
			}
			if(fmod(uv.y ,(radioy * 2)) < (radioy * 2) * _RimPower)
			{
				c = _RimColor;
			}

			o.Albedo = c.rgb;
			o.Alpha = 0.5;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}
我知道,以上写的很粗糙。。。但是,谁让我是pc上用的呢,谁还管效率是毛线
下一步,需要每套的脚本控制

2,脚本控制

主要是为了运行时,通过点击生成方格
using System.Collections.Generic;
using UnityEngine;

/**
 * 
 * 用于编辑器美术使用脚本,功能为画地形方块
 * 
 */
public class TerrianBlockControl : MonoBehaviour
{
    public int width;
    public int height;
    public Texture2D texture;
#if UNITY_EDITOR
    private Material material;
    private MeshRenderer meshRenderer;
<think>好的,用户的问题是如何解析OBJ文件将其转换为Unity中的Mesh对象。首先,我需要回忆一下OBJ文件的结构。OBJ文件通常包含顶点(v)、纹理坐标(vt)、法线(vn)和面(f)等数据。用户可能希望将这些数据提取出来,构建UnityMesh对象,以便在场景中显示模型。 接下来,我得查看用户提供的引用内容。引用[1]中提到OBJFile类,用于存储g、v、f数据,其中v对应mesh.vertices,f对应mesh.triangles。同时要注意Unity的索引从0开始,而OBJ文件中的索引可能从1开始,所以需要调整。引用[4]也提到v、vt、vn分别对应顶点坐标、纹理坐标和法线向量,而面数据可能包含这些索引的组合。 用户可能需要一个具体的步骤说明和代码示例。根据引用[3],异步加载时需要注意颜色设置的时机,这可能涉及到协程或者回调函数,但用户当前的问题可能更关注基础的解析过程,所以暂时先处理同步读取的情况。 首先,解析OBJ文件的每一行。以“v”开头的行是顶点,需要将坐标转换为Vector3存储。面的数据“f”可能格式复杂,例如“f 1/1/1 2/2/2 3/3/3”,需要提取顶点索引,处理可能的负数索引(相对索引)。同时,Unity的三角形列表需要将面数据转换为三个连续的整数,注意减去1,因为OBJ索引从1开始,而Unity从0开始。 然后,创建Mesh对象,将解析后的顶点和三角形数据赋值给mesh.vertices和mesh.triangles。可能还需要处理法线和UV,但根据用户提供的引用,可能暂时只处理基本顶点和面数据。另外,引用[2]提到使用MeshRenderer和Material,可能需要添加这些组件来显示模型。 需要检查代码示例是否正确处理了这些步骤,比如OBJFile类是否正确存储数据,解析面数据时是否拆分各部分,处理索引是否正确。同时要注意,有些OBJ文件可能包含四边形面,需要将其分割为三角形,但示例中可能假设面已经是三角形。 可能的问题包括索引转换错误、面数据解析不完整、忽略法线或UV导致模型显示不正确。需要确保示例代码能够处理这些情况,或者至少提供一个基础框架,用户可以在此基础上扩展。 最后,生成相关问题,帮助用户深入理解,比如如何处理材质、优化解析效率或处理复杂面结构。</think>### 如何解析OBJ文件转换为Unity Mesh对象 #### 步骤说明 1. **OBJ文件结构解析** OBJ文件包含顶点、法线、纹理坐标和面数据[^4]: - `v x y z`:顶点坐标(对应`Mesh.vertices`) - `f v1/vt1/vn1 v2/vt2/vn2 ...`:面数据(对应`Mesh.triangles`) 2. **创建数据存储类** 定义类存储解析后的数据(参考引用[1]): ```csharp public class OBJData { public List<Vector3> vertices = new List<Vector3>(); public List<int> triangles = new List<int>(); } ``` 3. **文件读取与解析** 逐行读取OBJ文件处理关键字段: ```csharp OBJData ParseOBJ(string filePath) { OBJData data = new OBJData(); string[] lines = File.ReadAllLines(filePath); foreach (string line in lines) { if (line.StartsWith("v ")) { // 解析顶点 string[] parts = line.Split(' '); Vector3 vertex = new Vector3( float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]) ); data.vertices.Add(vertex); } else if (line.StartsWith("f ")) { // 解析面(假设三角形面) string[] faceParts = line.Substring(2).Split(' '); foreach (string part in faceParts) { int vertexIndex = int.Parse(part.Split('/')[0]); // OBJ索引从1开始,Unity从0开始,需减1 data.triangles.Add(vertexIndex - 1); } } } return data; } ``` 4. **生成Unity Mesh对象** 将解析后的数据赋值给`Mesh`组件: ```csharp void CreateMesh(OBJData data) { Mesh mesh = new Mesh(); mesh.vertices = data.vertices.ToArray(); mesh.triangles = data.triangles.ToArray(); mesh.RecalculateNormals(); // 自动计算法线 GameObject obj = new GameObject("LoadedObject"); obj.AddComponent<MeshFilter>().mesh = mesh; obj.AddComponent<MeshRenderer>().material = new Material(Shader.Find("Standard")); // 参考引用[2] } ``` #### 注意事项 - **索引转换**:OBJ文件中`f 1 2 3`对应Unity中索引`0 1 2`[^1]。 - **异步加载**:大文件需用协程或异步方法避免卡顿(参考引用[3])。 - **复杂面处理**:若面包含四边形,需拆分为两个三角形。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值