Unity3D 사용자 정의 원추체 만 들 기

10274 단어 Unity3D원추체
머리말
요 며칠 동안 개인 작품 을 개발 하려 고 생각 하 다가 유 니 티 3D 공식 적 으로 원뿔 체 의 생 성 기능 을 제공 하지 않 고 스스로 편집기 확장 을 한 것 을 발견 했다.이전에 Mesh 프로 그래 밍 을 검색 할 때 자신의 알고리즘 을 명확 하 게 설명 하 는 블 로그 가 별로 없 었 기 때문에 여기 서 저 는 벽돌 을 던 져 옥 을 끌 어 들 였 습 니 다.제 가 할 수 있 는 한 일부 초보 자 들 에 게 참고 할 수 있 습 니 다.물론 알고리즘 이 반드시 좋 은 것 은 아 닙 니 다.만약 에 더 좋 은 알고리즘 이 있 고 기꺼이 알 게 된다 면 저 는 감사 하 겠 습 니 다.저 는 나이 가 들 어서 Unity 3D 개발 을 전 업 했 습 니 다.오 는 길에 모두 제 가 생각 하고 힘 들 었 습 니 다.먼저 감 사 드
소프트웨어 환경
Win10 + Unity3D 2017.3.0f3
본문
기본 적 인 사 고 는 원점 을 원뿔 체 밑부분 원 의 중심 점 으로 하고 그 바로 위 1 단원 의 점 을 원뿔 체 추 첨 의 정점 으로 하 며 다른 점 은 Cylinder 를 참조 하여 반경 0.5 단원 의 원 에 분포 하고 20 도 마다 한 점 씩 합 친 정점 수량 은 38 개 이 고 삼각형 색인 배열 의 수량 은 108 개(추 체 는 밑부분 원심 의 위로 이동 으로 볼 수 있다.그래서 이 두 부분의 삼각형 수량 은 같 고 바닥 은 20 도 에 한 점 씩 있 으 면 18 개의 삼각형 이 있 기 때문에 결 과 는 18*8727°3*8727°2=10818*8727°3*8727°2=108)이다.
다음은 점차적으로 분해 하여 실현 하기 시작한다.
편집기 확장
우선 확장 편집기,GameObject/3D Object 아래 Cone 메뉴 를 새로 만 듭 니 다.친자식 인 척 하기 위해 서 는 Cube 등 네 이 티 브 메뉴 와 함께 놓 으 세 요.

[MenuItem("GameObject/3D Object/Cone",false,priority = 7)]
public static void CreateCone()
{
 SpawnConeInHierarchy();
}
여 기 는 주로 MenuItem 특성 을 이용 하여 이 루어 진 것 입 니 다.그 중에서 false 는 이 메뉴 가 유효성 검증 이 필요 없다 고 표시 합 니 다.priority=7 제어 메뉴 가 표시 하 는 위 치 는 여 기 를 참고 할 수 있 습 니 다Unity 확장 Hierachry 오른쪽 단추 메뉴
편리 하 게 나 는 그림 을 아래 에 붙 였 다.


다음은 SpawnCone InHierarchy 방법 을 실현 합 니 다.

private static void SpawnConeInHierarchy()
 {
 Transform[] selections = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.ExcludePrefab);

 if (selections.Length <= 0)
 {
  GameObject cone = new GameObject("Cone");
  cone.transform.position = Vector3.zero;
  cone.transform.rotation = Quaternion.identity;
  cone.transform.localScale = Vector3.one;
  //SetMesh(cone);
  return;
 }

 foreach (Transform selection in selections)
 {
  GameObject cone = new GameObject("Cone");
  cone.transform.SetParent(selection);
  cone.transform.localPosition = Vector3.zero;
  cone.transform.localRotation = Quaternion.identity;
  cone.transform.localScale = Vector3.one;
  //SetMesh(cone);
 }
 }

여기 서 두 가지 상황 으로 나 뉘 는데,만약 Hierarchy 패 널 에서 어떤 물체 도 선택 하지 않 았 다 면,루트 디 렉 터 리 아래 에'Cone'이라는 게임 오 브 젝 트 를 생 성하 고,선택 한 물체 가 있 으 면 생 성 되 는'Cone'은 선택 한 항목 의 하위 물체 로 변 합 니 다.
PS:여기 버그 가 있 습 니 다.여러 개의 물 체 를 동시에 선택 하고 Hierarchy 패 널 오른쪽 단추 메뉴 를 사용 하면 선택 한 물체 마다 선택 한 물체 의 수량 과 같은 하위 물 체 를 생 성 합 니 다.다음 그림 을 보십시오.이 버그 는 버 전 2017.3 에 만 국한 되 지 않 을 것 이다.왜냐하면 내 가 인터넷 에서 같은 상황 의 게시 물 을 찾 았 기 때문이다.시간 은 2016 년 8 월 이다.

현재 이 버그 는 공식 확인 에 제출 했 습 니 다.그들 은 QA 에 전 달 했 지만 사용 에 영향 을 주지 않 습 니 다.피 하 는 방법 은 메뉴 를 오른쪽 클릭 하지 않 고 메뉴 표시 줄'GameObject'의 메뉴 를 클릭 하 는 것 입 니 다.
지금까지 편집기 메뉴 를 확 장 했 지만 빈 물체 가 생 성 되 었 습 니 다.그 다음 에 우 리 는 SetMesh 방법 을 실현 하여 Mesh 를 만 들 고 원뿔 체 를 표시 합 니 다.
메 쉬 생 성
두 부분 으로 나 누 어 먼저 아래쪽 의 원 을 그립 니 다.
원형 아래쪽 그리 기
원심 은 이미 원점 으로 확정 되 었 고 반지름 은 0.5f 이 며 원 에 모두 20 개의 점 이 분포 되 어 있 으 면 각 점 의 좌 표 는 삼각함수 로 계산 할 수 있다.

private static void SetMesh(GameObject go)
 {
 if (null == go)
  return;
 // Cylinder  
 float myRadius = 0.5f;
 int myAngleStep = 20;
 Vector3 myTopCenter = new Vector3(0, 1, 0);
 Vector3 myBottomCenter = Vector3.zero;
 //       UV  
 // 20     ,     ,        
 Vector3[] myVertices = new Vector3[360 / myAngleStep + 1];
 //  uv             ,        uv  
 Vector2[] myUV = new Vector2[myVertices.Length];
 //          ,   uv       
 myVertices[0] = myBottomCenter;
 myUV[0] = new Vector2(0.5f, 0.5f);
 //          
 for (int i = 1; i <= myVertices.Length / 2; i++)
 {
  float curAngle = i * myAngleStep * Mathf.Deg2Rad;
  float curX = myRadius * Mathf.Cos(curAngle);
  float curZ = myRadius * Mathf.Sin(curAngle);
  myVertices[i] = new Vector3(curX, 0, curZ);
  //       [-0.5,0.5], uv     [0,1],       
  myUV[i] = new Vector2(curX + 0.5f, curZ + 0.5f);
 }
그 다음 에 삼각형 색인 배열,19 개의 정점,모두 18 개의 삼각형 을 구축 하기 때문에 배열 의 길 이 는 18*3=54 이다.

int[] myTriangle = new int[(myVertices.Length - 1) * 3]; 
 //     (            )         
 for (int i = 0; i <= myTriangle.Length - 3; i = i+3)
 {
  //        
  myTriangle[i] = 0;
  //           ,          ,   (0 1 2 0 2 3...)
  myTriangle[i + 1] = i / 3 + 1;
  //              1
  myTriangle[i + 2] = i + 2 == myTriangle.Length / 2 - 1 ? 1 : i / 3 + 2;
  }
 }
마지막 으로 mesh,할당 소 재 를 분배 하면 원형 물 체 를 볼 수 있 습 니 다.

//  mesh
 Mesh myMesh = new Mesh();
 myMesh.name = "Cone";
 myMesh.vertices = myVertices;
 myMesh.triangles = myTriangle;
 myMesh.uv = myUV;
 myMesh.RecalculateBounds();
 myMesh.RecalculateNormals();
 myMesh.RecalculateTangents();
 //  mesh
 MeshFilter mf = go.AddComponent<MeshFilter>();
 mf.mesh = myMesh;
 //    
 MeshRenderer mr = go.AddComponent<MeshRenderer>();
 Material myMat = new Material(Shader.Find("Standard"));
 mr.sharedMaterial = myMat;

바닥 에 빛 이 없어 서 검은색 으로 보 입 니 다.또한 위의 코드 는 제 가 최종 코드 에서 수 동 으로 수정 한 것 입 니 다.오류 가 있 을 수 있 습 니 다.생각 을 이해 하 는 데 만 사용 되 고 전체 코드 는 마지막 에 제 시 됩 니 다.
완전 원추체
바닥 원 이 그 려 진 이상 추 체 는 원심 을 위로 옮 기 는 것 으로 이해 할 수 있 습 니 다.정점 수량 에 있어 서 삼각형 색인 배열 은 모두 double 에 해당 합 니 다.
여기 서 설명 할 수 있 는 상황 이 있 습 니 다.저 는 원래 원 의 정점 을 함께 사용 하려 고 했 습 니 다.그러면 전체 원뿔 의 정점 은 20 이지 만 테스트 를 통 해 안 됩 니 다.저 는 Cube 를 참 고 했 습 니 다.정점 은 24 이 고 서로 다른 면 의 정점 은 공유 할 수 없다 는 것 을 설명 합 니 다.아마도 법 선 방향 등 요소 때 문 일 것 입 니 다.
수 정 된 전체 코드 는 다음 과 같 습 니 다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;

public class ConeCreatorEditor
{

 [MenuItem("GameObject/3D Object/Cone",false,priority = 7)]
 public static void CreateCone()
 {
 SpawnConeInHierarchy();
 }


 private static void SetMesh(GameObject go)
 {
 if (null == go)
  return;
 // Cylinder  
 float myRadius = 0.5f;
 int myAngleStep = 20;
 Vector3 myTopCenter = new Vector3(0, 1, 0);
 Vector3 myBottomCenter = Vector3.zero;
 //       UV  
 Vector3[] myVertices = new Vector3[360 / myAngleStep * 2 + 2];
 //
 Vector2[] myUV = new Vector2[myVertices.Length];
 //                   
 myVertices[0] = myBottomCenter;
 myVertices[myVertices.Length - 1] = myTopCenter;
 myUV[0] = new Vector2(0.5f, 0.5f);
 myUV[myVertices.Length - 1] = new Vector2(0.5f,0.5f);
 //          ,      ,            
 for (int i = 1; i <= (myVertices.Length -2) / 2; i++)
 {
  float curAngle = i * myAngleStep * Mathf.Deg2Rad;
  float curX = myRadius * Mathf.Cos(curAngle);
  float curZ = myRadius * Mathf.Sin(curAngle);
  myVertices[i] = myVertices[i + (myVertices.Length - 2) / 2] = new Vector3(curX, 0, curZ);
  myUV[i] = myUV[i + (myVertices.Length - 2) / 2] = new Vector2(curX + 0.5f, curZ + 0.5f);

 }
 //       
 int[] myTriangle = new int[(myVertices.Length - 2) * 3]; 
 for (int i = 0; i <= myTriangle.Length - 3; i = i+3)
 {
  if (i + 2 < myTriangle.Length / 2)
  {
  myTriangle[i] = 0;
  myTriangle[i + 1] = i / 3 + 1;
  myTriangle[i + 2] = i + 2 == myTriangle.Length / 2 - 1 ? 1 : i / 3 + 2;
  }
  else
  {
  //      ,          
  myTriangle[i] = myVertices.Length - 1;
  //                  19
  myTriangle[i + 1] = i == myTriangle.Length - 3 ? 19 : i / 3 + 2;
  myTriangle[i + 2] = i / 3 + 1;
  }
 }

 //  mesh
 Mesh myMesh = new Mesh();
 myMesh.name = "Cone";
 myMesh.vertices = myVertices;
 myMesh.triangles = myTriangle;
 myMesh.uv = myUV;
 myMesh.RecalculateBounds();
 myMesh.RecalculateNormals();
 myMesh.RecalculateTangents();
 //  mesh
 MeshFilter mf = go.AddComponent<MeshFilter>();
 mf.mesh = myMesh;
 //    
 MeshRenderer mr = go.AddComponent<MeshRenderer>();
 Material myMat = new Material(Shader.Find("Standard"));
 mr.sharedMaterial = myMat;
 }

 private static void SpawnConeInHierarchy()
 {
 Transform[] selections = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.ExcludePrefab);

 if (selections.Length <= 0)
 {
  GameObject cone = new GameObject("Cone");
  cone.transform.position = Vector3.zero;
  cone.transform.rotation = Quaternion.identity;
  cone.transform.localScale = Vector3.one;
  //         
  Undo.RegisterCreatedObjectUndo(cone, "Undo Creating Cone");
  SetMesh(cone);
  return;
 }

 foreach (Transform selection in selections)
 {
  GameObject cone = new GameObject("Cone");
  cone.transform.SetParent(selection);
  cone.transform.localPosition = Vector3.zero;
  cone.transform.localRotation = Quaternion.identity;
  cone.transform.localScale = Vector3.one;
  //         
  Undo.RegisterCreatedObjectUndo(cone, "Undo Creating Cone");
  SetMesh(cone);
 }
 }
}

PS:여기 uv 설정 이 간단 하기 때문에 스티커 에 대한 요구 도 특정한 데 그렇지 않 으 면 그림 이 왜곡 되 고 필요 한 친구 가 스스로 수정 할 수 있 습 니 다.
결실

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기