Unity 단순 교환 시스템 실현

유 니 티 의 변장 에 대해 인터넷 에 몇 편의 글 이 있 는데 나 도 전에 간단하게 묘사 한 적 이 있다.근 데 그 때 는 대충 시험 해 봤 을 뿐 이 야.오늘 코드 를 잘 정 리 했 습 니 다.
먼저 코드 를 올 립 니 다.(자신의 게임 프로젝트 는 회사 의 것 이 아니 기 때문에 안심 하고 프로젝트 코드 를 붙 였 습 니 다.일 부 는 다른 기능 파일 에 인용 되 었 지만 핵심 코드 는 영향 을 주지 않 습 니 다.여기 서 디 테 일과 방향 을 살 펴 보 겠 습 니 다)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public enum AvatarPart
{
    helmet,
    chest,
    shoulders,
    gloves,
    boots,
}
 
//     
public class ActorAvatar : MonoBehaviour
{
    //        
    public class AvatarInfo
    {
        public string partName;
        public GameObject defaultPart;
        public GameObject avatarPart;
    }
 
    protected int _bodyModelId;
    protected GameObject _body;         //       
    protected Dictionary<string, AvatarInfo> _avatarInfo = new Dictionary<string, AvatarInfo>();        //     
 
    private List<int> _avatarLoadQueue = new List<int>();
 
    void Start()
    {
    }
 
    void Update()
    {
    }
 
    //     
    public void LoadModel(int modelId)
    {
        _bodyModelId = modelId;
        ResourceMgr.Instance.LoadModel(modelId, (GameObject obj) =>
        {
            _body = obj;
 
            //     
            if (_avatarLoadQueue.Count > 0) {
                foreach (var avatar in _avatarLoadQueue) {
                    LoadAvatar(avatar);
                }
                _avatarLoadQueue.Clear();
            }
        }, true);
    }
 
    //      
    public void LoadAvatar(int avatarId)
    {
        //             ,   
        if (_body == null) {
            _avatarLoadQueue.Add(avatarId);
            return;
        }
 
        AvatarData adata = DataMgr.Instance.GetAvatarData(avatarId);
        ResourceMgr.Instance.LoadModel(adata.model, (GameObject obj) => {
            ChangeAvatar(obj, adata.addpart);
        });
    }
 
    //     
    public void ChangeAvatar(GameObject avatarModel, string partName)
    {
        //        
        AvatarInfo currentInfo;
        if (_avatarInfo.TryGetValue(partName, out currentInfo)) {
            if (currentInfo.avatarPart != null) {
                Destroy(currentInfo.avatarPart);
                currentInfo.avatarPart = null;
            }
 
            if (currentInfo.defaultPart != null) {
                currentInfo.defaultPart.SetActive(true);
            }
        }
 
        // avatarModel   resource,      
        if (avatarModel == null) {
            return;
        }
 
        //        
        Transform avatarPart = GetPart(avatarModel.transform, partName);
        if (avatarPart == null) {
            Debug.LogError(string.Format("Avatar Part Not Found: ", partName));
            return;
        }
 
        //        
        Transform bodyPart = GetPart(_body.transform, partName);
        if (bodyPart != null) {
            bodyPart.gameObject.SetActive(false);
        }
 
        //    body     
        GameObject newPart = new GameObject(partName);
        newPart.transform.parent = _body.transform;
        SkinnedMeshRenderer newPartRender = newPart.AddComponent<SkinnedMeshRenderer>();
        SkinnedMeshRenderer avatarRender = avatarPart.GetComponent<SkinnedMeshRenderer>();
 
        //         
        SetBones(newPart, avatarPart.gameObject, _body);
        newPartRender.sharedMesh = avatarRender.sharedMesh;
        newPartRender.sharedMaterials = avatarRender.sharedMaterials;
 
        //       
        AvatarInfo info = new AvatarInfo();
        info.partName = partName;
        if (bodyPart != null) {
            info.defaultPart = bodyPart.gameObject;
        } else {
            info.defaultPart = null;
        }
 
        info.avatarPart = newPart;
        _avatarInfo[partName] = info;
    }
 
     //        
    public static Transform GetPart(Transform t, string searchName)
    {
        foreach (Transform c in t) {
            string partName = c.name.ToLower();
            
            if (partName.IndexOf(searchName) != -1) {
                return c;
            } else {
                Transform r = GetPart(c, searchName);
                if (r != null) {
                    return r;
                }
            }
        }
        return null;
    }
 
    public static Transform FindChild(Transform t, string searchName)
    {
        foreach (Transform c in t) {
            string partName = c.name;
            if (partName == searchName) {
                return c;
            } else {
                Transform r = FindChild(c, searchName);
                if (r != null) {
                    return r;
                }
            }
        }
        return null;
    }
 
    //           root   bodyPart     avatarPart
    public static void SetBones(GameObject goBodyPart, GameObject goAvatarPart, GameObject root)
    {
        var bodyRender = goBodyPart.GetComponent<SkinnedMeshRenderer>();
        var avatarRender = goAvatarPart.GetComponent<SkinnedMeshRenderer>();
        var myBones = new Transform[avatarRender.bones.Length];
        for (var i = 0; i < avatarRender.bones.Length; i++) {
            myBones[i] = FindChild(root.transform, avatarRender.bones[i].name);
        }
        bodyRender.bones = myBones;
    }
 
}
1.Unity 는 세 가지 수요 가 있 습 니 다.
무기 마 운 트 방식 을 추가 합 니 다.이것 은 해당 하 는 모델 을 만 들 고 transform.parent 를 설정 하면 됩 니 다.
텍 스 처 를 바 꾸 고 해당 하 는 material 를 가 져 와 texture 를 설정 하면 됩 니 다.
모형 부품 의 교체,이것 은 여기에서 처리 한 것 이 며,상대 적 으로 가장 복잡 한 교체 이다.
2.가장 핵심 적 인 부분 은 Change Avatar 로 모델 교환 기능 을 완성 했다.모델 부품 의 교 체 는 사실 Skinned Mesh Render 의 shared Mesh 와 shared Materials 를 교체 하 는 것 입 니 다.
(여기에 shared Materials 를 살짝 꽂 아 주세요.  sharedMaterial  Materials  Material 라 는 변수의 차이 점shared Materials 는 공유 와 인용의 관계 로 이것 만 수정 하면 이 material 에 사용 되 는 모든 모델 이 영향 을 받는다.편집기 모드 에서 실제 material 파일 의 속성 을 수정 합 니 다.Materials 는 shared Materials 의 복사 본 으로 현재 모델 만 사용 합 니 다.materia 는 materials 배열 의 첫 번 째 대상 으로 쓰기 편 하도록 존재 합 니 다.)
shared Mesh 를 교체 하 는 것 만 으로 는 부족 합 니 다.모델 은 꽈배기 가 됩 니 다. 또한 Skinned MeshRender 의 bones 속성 을 수정 해 야 합 니 다.모델 의 뼈 정 보 를 기록 합 니 다(사실은 Transform 입 니 다). SetBones 함수 가 골격 교체 작업 을 완 료 했 습 니 다.이것 은 avatar 위 젯 의 모든 골격 이름 을 찾 은 다음 현재 모델 에 대응 하 는 골격 이름 을 찾 아 저장 합 니 다.이 배열 은 바로 새 부품 의 골격 정보 이다.
3.논리 적 인 처리 세부 사항원본 모델 에 대응 하 는 위 젯 을 보존 하고 이 위 젯 을 소각 하지 않 고 숨 겼 습 니 다.이렇게 장 비 를 마 운 트 해제 할 때 는 장비 부품 을 삭제 하고 기본 부품 을 보 이 는 것 으로 설정 하면 된다.
4.Unity 의 CombineInstance 를 사용 하여 모델 을 합병 하 는 것 을 고려 할 수 있 는데 이런 장점 은 운행 성능 을 향상 시 킬 수 있다 는 것 이다.하지만 재질 이 하 나 를 공용 할 때 만 진정 으로 최적화 효 과 를 낼 수 있다.MeshBaker 플러그 인 이 멋 있어 요.천인 전 을 치 르 려 면,이 방면 의 최 적 화 를 고려 해 야 한다.

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

좋은 웹페이지 즐겨찾기