unity開發游戲實現角色篩選預覽

RenderTexture通俗解釋

RenderTexture就像是Unity中的"虛擬相機膠片",它可以:

  1. 捕獲3D內容:將3D場景或對象"拍照"記錄下來
  1. 實時更新:不是靜態圖片,而是動態視頻,角色可以動起來
  1. 用作紋理:可以顯示在UI界面上

在角色預覽系統中的作用

從你的截圖和代碼中可以看出:

  1. 分離渲染:CharacterPreviewRT(512×512分辨率)專門用來渲染角色模型
  1. 橋梁作用:連接了3D世界和2D界面
  • 3D世界:CharacterPreviewCamera(相機)拍攝放在CharacterPosition(位置)的角色模型
  • 2D界面:通過RawImage顯示這個"拍攝"結果
  1. 性能優化:
  • 只渲染需要的角色,不渲染整個場景
  • 可以控制渲染質量(如你設置的2×抗鋸齒)
  1. 交互實現:
  • 你的代碼中的HandleCharacterRotation()方法讓用戶可以旋轉預覽角色

實現思路(我的界面結構參考)

?

創建一個顯示的面板(CharacterInfoPanel),并且添加組件(重要)

界面參考布局

相機配置注意配置Culling Mask為對應的層級

?

代碼參考:

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using Game.Managers;namespace Game.UI
{/// <summary>/// 角色選擇面板,處理角色瀏覽、選擇和預覽功能/// </summary>public class CharacterSelectPanel : BasePanel{[Header("角色列表")][SerializeField] private Transform characterListContainer; // 角色列表容器[SerializeField] private GameObject characterItemPrefab;   // 角色選項預制體[SerializeField] private ScrollRect characterScrollRect;   // 角色列表滾動視圖[Header("角色預覽")][SerializeField] private RawImage characterPreviewImage;   // 角色預覽圖像[SerializeField] private Transform characterPosition;      // 角色位置[Header("按鈕")][SerializeField] private Button confirmButton;             // 確認按鈕[Header("旋轉設置")][SerializeField] private float rotationSpeed = 30f;        // 旋轉速度// 角色數據private List<CharacterData> characterDataList = new List<CharacterData>();// 預覽相關private GameObject currentPreviewCharacter;private bool isDragging = false;private float lastMouseX;private int selectedCharacterIndex = -1;private List<CharacterItemUI> characterItemUIs = new List<CharacterItemUI>();protected override void Initialize(){base.Initialize();Debug.Log("[CharacterSelectPanel] 初始化面板");// 驗證組件引用if(characterPosition == null)Debug.LogError("[CharacterSelectPanel] characterPosition未設置,請將預覽位置拖拽到Inspector面板");if(characterPreviewImage == null)Debug.LogError("[CharacterSelectPanel] characterPreviewImage未設置,請將RawImage拖拽到Inspector面板");if(characterItemPrefab == null)Debug.LogError("[CharacterSelectPanel] characterItemPrefab未設置,請將角色項預制體拖拽到Inspector面板");// 檢查角色項預制體是否包含必要組件CharacterItemUI testItemUI = characterItemPrefab.GetComponent<CharacterItemUI>();if(testItemUI == null)Debug.LogError("[CharacterSelectPanel] 角色項預制體必須包含CharacterItemUI組件!請在預制體上添加此組件");// 初始化組件引用if (confirmButton != null){confirmButton.onClick.AddListener(OnConfirmButtonClicked);confirmButton.interactable = false; // 初始狀態下禁用確認按鈕}// 加載角色數據LoadCharacterData();// 初始化角色列表PopulateCharacterList();}protected override void SetupButtons(){base.SetupButtons();// 可以在這里添加其他按鈕的監聽器}void Update(){// 處理角色旋轉HandleCharacterRotation();}/// <summary>/// 處理角色旋轉/// </summary>private void HandleCharacterRotation(){if (characterPreviewImage == null || currentPreviewCharacter == null) return;// 檢查預覽圖片上的鼠標事件if (RectTransformUtility.RectangleContainsScreenPoint(characterPreviewImage.rectTransform, Input.mousePosition)){// 鼠標按下開始拖動if (Input.GetMouseButtonDown(0)){isDragging = true;lastMouseX = Input.mousePosition.x;}}// 松開鼠標停止拖動if (Input.GetMouseButtonUp(0)){isDragging = false;}// 拖動時旋轉角色if (isDragging && currentPreviewCharacter != null){float deltaX = Input.mousePosition.x - lastMouseX;currentPreviewCharacter.transform.Rotate(0, -deltaX * rotationSpeed * Time.deltaTime, 0);lastMouseX = Input.mousePosition.x;}}/// <summary>/// 加載角色數據/// </summary>private void LoadCharacterData(){Debug.Log("[CharacterSelectPanel] 加載角色數據");// 理想情況下,這些數據應該從DataManager或資源文件加載// 這里為演示創建一些測試數據characterDataList.Clear();// 簡化測試數據,只包含必要信息characterDataList.Add(new CharacterData(0, "戰士", "", "Characters/Warrior"));characterDataList.Add(new CharacterData(1, "忍者", "", "Characters/Ninja"));characterDataList.Add(new CharacterData(2, "魔法師", "", "Characters/Mage"));characterDataList.Add(new CharacterData(3, "武僧", "", "Characters/Monk"));Debug.Log($"[CharacterSelectPanel] 已加載{characterDataList.Count}個角色數據");}/// <summary>/// 填充角色列表/// </summary>private void PopulateCharacterList(){if (characterListContainer == null){Debug.LogError("[CharacterSelectPanel] characterListContainer未設置,無法填充角色列表");return;}if (characterItemPrefab == null){Debug.LogError("[CharacterSelectPanel] characterItemPrefab未設置,無法填充角色列表");return;}Debug.Log("[CharacterSelectPanel] 填充角色列表");// 清空現有列表和記錄foreach (Transform child in characterListContainer){Destroy(child.gameObject);}characterItemUIs.Clear();// 為每個角色創建列表項for (int i = 0; i < characterDataList.Count; i++){CharacterData data = characterDataList[i];GameObject item = Instantiate(characterItemPrefab, characterListContainer);item.name = $"CharacterItem_{data.name}";// 配置角色項CharacterItemUI itemUI = item.GetComponent<CharacterItemUI>();if (itemUI != null){int index = i; // 創建局部變量以便在閉包中使用itemUI.Setup(data);itemUI.OnItemSelected += () => OnCharacterItemSelected(index);characterItemUIs.Add(itemUI);Debug.Log($"[CharacterSelectPanel] 創建角色列表項: {data.name}");}else{Debug.LogError($"[CharacterSelectPanel] 角色列表項預制體上沒有CharacterItemUI組件!");}}}/// <summary>/// 角色項被選中/// </summary>private void OnCharacterItemSelected(int index){if (index < 0 || index >= characterDataList.Count) return;Debug.Log($"[CharacterSelectPanel] 選擇角色: {characterDataList[index].name}");// 更新選中的角色索引selectedCharacterIndex = index;CharacterData data = characterDataList[index];// 更新角色項UI狀態for (int i = 0; i < characterItemUIs.Count; i++){if (characterItemUIs[i] != null){characterItemUIs[i].SetSelected(i == index);}}// 加載角色預覽LoadCharacterPreview(data.prefabPath);// 啟用確認按鈕if (confirmButton != null)confirmButton.interactable = true;}/// <summary>/// 加載角色預覽/// </summary>private void LoadCharacterPreview(string prefabPath){Debug.Log($"[CharacterSelectPanel] 開始加載角色預覽: {prefabPath}");if (characterPosition == null){Debug.LogError("[CharacterSelectPanel] characterPosition未設置,無法加載角色預覽");return;}// 清除當前預覽角色if (currentPreviewCharacter != null){Destroy(currentPreviewCharacter);currentPreviewCharacter = null;}// 加載角色預制體GameObject characterPrefab = Resources.Load<GameObject>(prefabPath);if (characterPrefab == null){Debug.LogError($"[CharacterSelectPanel] 無法加載角色預制體: {prefabPath},請檢查路徑是否正確并且確保預制體存在于Resources目錄");return;}Debug.Log($"[CharacterSelectPanel] 成功加載角色預制體: {prefabPath}");// 實例化新角色currentPreviewCharacter = Instantiate(characterPrefab, characterPosition);// 設置層和位置int previewLayer = LayerMask.NameToLayer("CharacterPreview");if (previewLayer < 0){Debug.LogError("[CharacterSelectPanel] 未找到'CharacterPreview'層,請在項目設置中添加此層");previewLayer = 0; // 使用默認層}currentPreviewCharacter.layer = previewLayer;SetLayerRecursively(currentPreviewCharacter, previewLayer);// 重置位置和旋轉currentPreviewCharacter.transform.localPosition = Vector3.zero;currentPreviewCharacter.transform.localRotation = Quaternion.identity;// 播放待機動畫(如果有)Animator animator = currentPreviewCharacter.GetComponent<Animator>();if (animator != null){animator.Play("Idle");Debug.Log("[CharacterSelectPanel] 已播放Idle動畫");}else{Debug.Log("[CharacterSelectPanel] 角色沒有Animator組件,跳過動畫播放");}Debug.Log($"[CharacterSelectPanel] 角色預覽加載完成: {prefabPath}");}/// <summary>/// 遞歸設置物體及其子物體的層/// </summary>private void SetLayerRecursively(GameObject obj, int layer){obj.layer = layer;foreach (Transform child in obj.transform){SetLayerRecursively(child.gameObject, layer);}}/// <summary>/// 確認按鈕點擊事件/// </summary>private void OnConfirmButtonClicked(){if (selectedCharacterIndex < 0){Debug.LogWarning("請先選擇一個角色");return;}// 保存選擇的角色if (DataManager.Instance != null){DataManager.Instance.SetSelectedCharacter(selectedCharacterIndex);}Debug.Log($"確認選擇角色: {characterDataList[selectedCharacterIndex].name}");// 隱藏角色選擇面板Hide();// 進入戰斗場景if (GameManager.Instance != null){GameManager.Instance.ChangeState(GameState.Battle);}}protected override void OnPanelShow(){base.OnPanelShow();Debug.Log("[CharacterSelectPanel] 顯示面板");// 重置選擇狀態selectedCharacterIndex = -1;if (confirmButton != null)confirmButton.interactable = false;// 清除當前預覽if (currentPreviewCharacter != null){Destroy(currentPreviewCharacter);currentPreviewCharacter = null;}}protected override void OnBackButtonClicked(){Debug.Log("[CharacterSelectPanel] 返回按鈕點擊");Hide();// 返回難度選擇界面UIManager.Instance.ShowDifficultySelectPanel();}}/// <summary>/// 角色數據類/// </summary>[System.Serializable]public class CharacterData{public int id;public string name;public string description;public string prefabPath;public CharacterData(int id, string name, string description, string prefabPath){this.id = id;this.name = name;this.description = description;this.prefabPath = prefabPath;}}
} 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906073.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906073.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906073.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring源碼主線全鏈路拆解:從啟動到關閉的完整生命周期

Spring源碼主線全鏈路拆解&#xff1a;從啟動到關閉的完整生命周期 一文看懂 Spring 框架從啟動到銷毀的主線流程&#xff0c;結合原理、源碼路徑與偽代碼三位一體&#xff0c;系統學習 Spring 底層機制。 1. 啟動入口與環境準備 原理說明 Spring Boot 應用入口是標準 Java 應…

SAP RF 移動屏幕定制

SAP RF 移動屏幕定制 ITSmobile 是 SAP 當前將移動設備連接到 SAP 系統的技術基礎。它基于 SAP Internet Transaction Server (ITS)&#xff0c;從 Netweaver 2004 開始作為 Netweaver 平臺的一部分提供。ITSmobile 提供了一個框架&#xff0c;用于為任何 SAP 事務生成基于 HT…

Spark,數據提取和保存

以下是使用 Spark 進行數據提取&#xff08;讀取&#xff09;和保存&#xff08;寫入&#xff09;的常見場景及代碼示例&#xff08;基于 Scala/Java/Python&#xff0c;不含圖片操作&#xff09;&#xff1a; 一、數據提取&#xff08;讀取&#xff09; 1. 讀取文件數據&a…

如何用mockito+junit測試代碼

Mockito 是一個流行的 Java 模擬測試框架&#xff0c;用于創建和管理測試中的模擬對象(mock objects)。它可以幫助開發者編寫干凈、可維護的單元測試&#xff0c;特別是在需要隔離被測組件與其他依賴項時。 目錄 核心概念 1. 模擬對象(Mock Objects) 2. 打樁(Stubbing) 3. 驗…

最新缺陷檢測模型:EPSC-YOLO(YOLOV9改進)

目錄 引言:工業缺陷檢測的挑戰與突破 一、EPSC-YOLO整體架構解析 二、核心模塊技術解析 1. EMA多尺度注意力模塊:讓模型"看得更全面" 2. PyConv金字塔卷積:多尺度特征提取利器 3. CISBA模塊:通道-空間注意力再進化 4. Soft-NMS:更智能的重疊框處理 三、實…

【Linux網絡與網絡編程】12.NAT技術內網穿透代理服務

1. NAT技術 之前我們說到過 IPv4 協議中IP 地址數量不充足的問題可以使用 NAT 技術來解決。還提到過本地主機向公網中的一個服務器發起了一個網絡請求&#xff0c;服務器是怎么將應答返回到該本地主機呢&#xff1f;&#xff08;如何進行內網轉發&#xff1f;&#xff09; 這就…

uniapp的適配方式

文章目錄 前言? 一、核心適配方式對比&#x1f4cf; 二、rpx 單位&#xff1a;uni-app 的核心適配機制&#x1f9f1; 三、默認設計稿適配&#xff08;750寬&#xff09;&#x1f501; 四、字體 & 屏幕密度適配&#x1f6e0; 五、特殊平臺適配&#xff08;底部安全區、劉海…

JAVA EE(進階)_進階的開端

別放棄浸透淚水的昨天&#xff0c;晨光已為明天掀開新篇 ——陳長生. ?主頁&#xff1a;陳長生.-CSDN博客? &#x1f4d5;上一篇&#xff1a;JAVA EE_HTTP-CSDN博客 1.什么是Java EE Java EE&#xff08;Java Pla…

SQL腳本規范

主要作用&#xff1a;數據庫的備份和遷移 SQL腳本規范 每一個sql語句必須與;結束 腳本結構&#xff1a; { 刪庫&#xff0c;建庫 刪表&#xff0c;建表 插入初始數據 } 建庫語法&#xff1a; CREATE DATABASE 數據庫名CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CHARA…

std::ratio<1,1000> 是什么意思?

author: hjjdebug date: 2025年 05月 14日 星期三 09:45:24 CST description: std::ratio<1,1000> 是什么意思&#xff1f; 文章目錄 1. 它是一種數值嗎&#xff1f;2. 它是一種類型嗎&#xff1f;3. std:ratio 是什么呢&#xff1f;4. 分析一個展開后的模板函數5.小結: …

測試--測試分類 (白盒 黑盒 單元 集成)

一、按照測試目標分類&#xff08;測試目的是什么&#xff09; 主類別細分說明1. 界面測試UI內容完整性、一致性、準確性、友好性&#xff0c;布局排版合理性&#xff0c;控件可用性等2. 功能測試檢查軟件功能是否符合需求說明書&#xff0c;常用黑盒方法&#xff1a;邊界值、…

整理了 2009 - 2025 年的【199 管綜真題 + 解析】PDF,全套共 34 份文件

每年真題原卷 ? 每年詳細解析 ? &#x1f4c2;【管綜真題 2009-2025】 &#x1f4c2;【管綜解析 2009-2025】 目錄樹&#xff1a; ├── 2009-2025管綜真題 PDF │ ├── 2009年199管綜真題.pdf │ ├── 2010年199管綜真題.pdf │ ├── 2011年199管綜真題.pd…

用golang實現二叉搜索樹(BST)

目錄 一、概念、性質二、二叉搜索樹的實現1. 結構2. 查找3. 插入4. 刪除5. 中序遍歷 中序前驅/后繼結點 一、概念、性質 二叉搜索樹&#xff08;Binary Search Tree&#xff09;&#xff0c;簡寫BST&#xff0c;又稱為二叉查找樹 它滿足&#xff1a; 空樹是一顆二叉搜索樹對…

自動化:批量文件重命名

自動化&#xff1a;批量文件重命名 1、前言 2、效果圖 3、源碼 一、前言 今天來分享一款好玩的自動化腳&#xff1a;批量文件重命名 有時候呢&#xff0c;你的文件被下載下來文件名都是亂七八糟毫無規律&#xff0c;但是當時你下載的時候沒辦法重名或者你又不想另存為重新重…

VueUse/Core:提升Vue開發效率的實用工具庫

文章目錄 引言什么是VueUse/Core&#xff1f;為什么選擇VueUse/Core&#xff1f;核心功能詳解1. 狀態管理2. 元素操作3. 實用工具函數4. 瀏覽器API封裝5. 傳感器相關 實戰示例&#xff1a;構建一個拖拽上傳組件性能優化技巧與原生實現對比常見問題解答總結 引言 在現代前端開發…

stm32 ADC單通道轉換

stm32c8t6僅有12位分辨率 1、單次轉換 非掃描 1、初始化 void Ad_Init() {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//配置ADCCLK時鐘分頻,ADC的輸入時鐘不得超過14MHzRCC_ADCCLKConfig(RCC_PCLK2_Div6);G…

2KW壓縮機驅動參考設計【SCH篇】

實物展示&#xff1a; ACDC: VAC和VAC-為交流電壓檢測&#xff1a; 1.C33 C34作為Y電容走線寬度要求&#xff1a; Y電容一般用于L/N到地之間&#xff08;L-PE 或 N-PE&#xff09;&#xff0c;主要作用是抑制共模干擾。其走線的電流非常小&#xff0c;推薦使用 ≥ 1mm 寬的走…

python05——循環結構

1、while循環 n0 #初始條件 while n<5: #判斷print(hello python) #要重復執行的代碼print(n) #注意同級代碼縮進相同n1 #計數器結果&#xff1a; hello python 0 hello python 1 hello python 2 hello python 3 hello python 4 hello python 5 #求階乘和 sum0 n1 whil…

LINUX編譯、運行、測試lowcoder_CN

參考 二者沒有太大差異。 LINUX編譯、運行、測試lowcoder-CSDN博客 下載 git clone https://github.com/mousheng/lowcoder_CN 或 git clone https://gitcode.com/gh_mirrors/lo/lowcoder_CNcd lowcoder_CN三個模塊 node-service api-service client 每個模塊都有自己的…

Python 基礎之函數命名

幾個問題 使用描述性蛇形命名法&#xff08;snake_case&#xff09;Python函數名應使用什么大小寫格式&#xff1f;為什么函數名要具有描述性&#xff1f;方法的命名規范是什么&#xff1f;函數、變量和類的命名有何區別&#xff1f; Python函數的命名有一些不可違背的硬性規…