深度解析:TextRenderManager——Cocos Creator藝術字體渲染核心類

一、類概述

TextRenderManager?是 Cocos Creator 中實現動態藝術字體渲染的核心單例類。它通過整合資源加載、緩存管理、異步隊列和自動布局等功能,支持普通字符模式圖集模式兩種渲染方案,適用于游戲中的動態文本(如聊天內容、排行榜)和靜態藝術字(如UI標題)的高效渲染。

二、核心功能與設計理念

1.?核心功能

  • 資源預加載:分批次異步加載字符紋理或圖集,避免主線程阻塞。

  • 動態緩存管理:通過LRUCache實現字符紋理的智能緩存與淘汰。

  • 自動布局排版:支持水平對齊(左/中/右)、垂直對齊(上/中/下)及字符間距調整。

  • 多模式渲染

    • 普通模式:從獨立文件加載每個字符的紋理。

    • 圖集模式:從預生成的圖集(如BMFont輸出)中提取字符。

2.?設計目標

  • 高性能:通過異步加載、LRU緩存減少資源重復請求。

  • 易擴展:模塊化設計,支持自定義布局策略與渲染模式。

  • 內存安全:動態釋放無用資源,防止內存泄漏。

三、代碼結構與核心方法詳解

1.?私有屬性與緩存機制

// 字符紋理緩存(LRU策略)
private _spriteCache = new LRUCache<string, SpriteFrame>(100);
// 加載隊列(防止重復請求)
private _loadingQueue = new Map<string, Promise<void>>();
// 渲染請求隊列(異步任務調度)
private _requestQueue: Array<{ text: string, config: TextRenderConfig, resolve: Function }> = [];
// 占位符紋理(加載失敗時使用)
private _placeholderCache: SpriteFrame | null = null;

2.?核心方法解析

(1) 文本渲染入口:renderText()
/*** 渲染文本* @param text 文本內容* @param config 渲染配置* @returns 包含所有字符節點的容器*/
public async renderText(text: string, config: TextRenderConfig = {}): Promise<Node> {return new Promise((resolve) => {// 將請求加入隊列,觸發異步處理this._requestQueue.push({ text, config, resolve });this._processQueue();});
}
  • 流程

    1. 將渲染請求推入隊列,確保異步任務按順序執行。

    2. 調用_processQueue()處理隊列中的任務。


(2) 隊列處理器:_processQueue()
/** 處理渲染隊列(單線程異步執行) */
private async _processQueue() {if (this._isProcessing || this._requestQueue.length === 0) return;this._isProcessing = true;const { text, config, resolve } = this._requestQueue.shift()!;try {const container = await this._doRender(text, config);resolve(container);} finally {this._isProcessing = false;this._processQueue(); // 遞歸處理下一個任務}
}
  • 關鍵點

    • 使用_isProcessing狀態鎖防止并發處理。

    • 通過遞歸調用實現隊列的持續消費。


(3) 實際渲染邏輯:_doRender()
/** 執行實際渲染邏輯 */
private async _doRender(text: string, config: TextRenderConfig): Promise<Node> {const container = new Node('TextContainer');this._applyConfig(config, container); // 應用配置(位置、父節點等)// 預加載資源(字符或圖集)try {if (config.useAtlas) {await this._loadAtlas(config);} else {await this._preloadCharacters(text, config);}} finally {if (config.preRender) {container.destroy(); // 預渲染模式直接銷毀容器return;}}// 創建字符節點并布局const nodes = await this._createCharacterNodes(text, config);this._layoutNodes(nodes, config);// 設置字符縮放并添加到容器nodes.forEach(node => {container.addChild(node);if (config.fontSize) {node.setScale(new Vec3(config.fontSize / 100, config.fontSize / 100, 1));}});return container;
}
  • 流程

    1. 配置初始化:設置容器位置、父節點等基礎屬性。

    2. 資源預加載:根據配置選擇加載圖集或獨立字符。

    3. 字符節點創建:生成所有字符的Sprite節點。

    4. 布局計算:根據對齊方式排列字符位置。


(4) 字符預加載:_preloadCharacters()
/** 預加載字符資源(分批次加載) */
private async _preloadCharacters(text: string, config: TextRenderConfig) {const uniqueChars = [...new Set(text.split(''))];// 分批次加載(每批5個字符)for (let i = 0; i < uniqueChars.length; i += 5) {const batch = uniqueChars.slice(i, i + 5);await Promise.all(batch.map(char => this._loadWithCacheControl(char, config)));}
}
  • 優化策略

    • 分批加載減少瞬時資源請求壓力。

    • 使用_loadWithCacheControl結合LRU緩存管理。


(5) 布局計算:_layoutNodes()
/** 自動布局字符節點 */
private _layoutNodes(nodes: Node[], config: TextRenderConfig) {const firstNode = nodes[0]?.getComponent(Sprite);if (!firstNode?.spriteFrame) return;// 計算總寬度和基礎高度const baseHeight = firstNode.spriteFrame.rect.height;const totalWidth = nodes.reduce((sum, node) => sum + node.getComponent(Sprite)!.spriteFrame.rect.width, 0) + (nodes.length - 1) * (config.spacing || 0);// 計算起始位置let xPos = this._calculateXPosition(totalWidth, config.alignment);const yPos = this._calculateYPosition(baseHeight, config.verticalAlign);// 排列節點nodes.forEach(node => {const width = node.getComponent(Sprite)!.spriteFrame.rect.width;node.setPosition(xPos, yPos, 0);xPos += width + (config.spacing || 0);});
}
  • 布局邏輯

    • 水平對齊:根據alignment計算起始X坐標。

    • 垂直對齊:根據verticalAlign計算起始Y坐標。

    • 動態間距:累加每個字符的寬度與間距,實現自動換行(如需)。


(6) 占位符生成:_getPlaceholder()
/** 生成透明占位符紋理 */
private _getPlaceholder(): SpriteFrame {if (!this._placeholderCache) {const frame = new SpriteFrame();const charWidth = 30, charHeight = 30; // 與實際字符尺寸一致const texture = new Texture2D();texture.create(charWidth, charHeight, Texture2D.PixelFormat.RGBA8888);const data = new Uint8Array(charWidth * charHeight * 4).fill(150); // 半透明灰色texture.uploadData(data);frame.rect = new Rect(0, 0, charWidth, charHeight);frame.texture = texture;this._placeholderCache = frame;}return this._placeholderCache;
}
  • 作用

    • 在字符加載失敗時提供占位顯示,避免UI錯亂。

    • 使用透明紋理減少視覺干擾。


3.?關鍵配置參數:TextRenderConfig

/** 生成透明占位符紋理 */
private _getPlaceholder(): SpriteFrame {if (!this._placeholderCache) {const frame = new SpriteFrame();const charWidth = 30, charHeight = 30; // 與實際字符尺寸一致const texture = new Texture2D();texture.create(charWidth, charHeight, Texture2D.PixelFormat.RGBA8888);const data = new Uint8Array(charWidth * charHeight * 4).fill(150); // 半透明灰色texture.uploadData(data);frame.rect = new Rect(0, 0, charWidth, charHeight);frame.texture = texture;this._placeholderCache = frame;}return this._placeholderCache;
}

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

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

相關文章

【漫話機器學習系列】229.特征縮放對梯度下降的影響(The Effect Of Feature Scaling Gradient Descent)

特征縮放對梯度下降的影響&#xff1a;為什么特征標準化如此重要&#xff1f; 在機器學習和深度學習中&#xff0c;梯度下降是最常用的優化算法之一。然而&#xff0c;很多人在訓練模型時會遇到收斂速度慢、訓練不穩定的問題&#xff0c;其中一個重要原因就是特征未進行適當的…

【神經網絡與深度學習】批標準化(Batch Normalization)和層標準化(Layer Normalization)

引言 在深度學習中&#xff0c;標準化技術&#xff08;Normalization&#xff09;是提高神經網絡訓練效率和性能的重要工具。其中&#xff0c;批標準化&#xff08;Batch Normalization, BN&#xff09;和層標準化&#xff08;Layer Normalization, LN&#xff09;是兩種常用的…

OpenHarmony之電源管理子系統公共事件定義

OpenHarmony之電源管理子系統公共事件定義 電源管理子系統面向應用發布如下系統公共事件&#xff0c;應用如需訂閱系統公共事件&#xff0c;請參考公共事件接口文檔。 COMMON_EVENT_BATTERY_CHANGED 表示電池充電狀態、電平和其他信息發生變化的公共事件的動作。 值&#x…

linux 環境下 c++ 程序打印 core dump 信息

linux 信號機制 軟中斷信號 Signal&#xff0c;簡稱信號&#xff0c;用來通知進程發生了異步事件&#xff0c;進程之間可以互相通過系統調用 kill 等函數來發送軟中斷信號。內核也可以因為內部事件而給進程發送信號&#xff0c;通知進程發生了某個事件。 進程對信號的處理 進…

Qt開發環境的安裝與問題的解決(2)

文章目錄 1. Qt開發環境安裝的說明2. 通過安裝包進行安裝3. 通過在線下載程序 解決問題下載 https....網路錯誤問題解決開始安裝--第一部分開始安裝--第二部分 4. 建議配置環境變量&#xff08;非必須&#xff09;配置環境變量的意義 簡介&#xff1a;這篇文章主要分享Qt開發環…

【每日EDA行業分析】2025年4月25日

深度總結&#xff1a;EDA 軟件行業現狀與發展趨勢 一、引言 在半導體產業的復雜生態中&#xff0c;EDA 軟件宛如一顆閃耀的明珠&#xff0c;它是集成電路設計的核心工具&#xff0c;貫穿芯片從設計構思到最終封裝測試的全流程&#xff0c;其重要性不言而喻&#xff0c;被譽為…

flutter實踐:比例對比線圖實現

需求&#xff1a;flutter實現一個左右對比線圖,帶有動畫效果 效果圖&#xff1a; Widget _buildTop() {return Container(height: themeData.heightXl,padding: EdgeInsets.symmetric(horizontal: themeData.hSpacingMd),child: Row(mainAxisAlignment: MainAxisAlignment.spa…

測試基礎筆記第十五天

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 一、集合1.集合的定義二、使用集合列表去重 導包二、函數1.函數介紹2.定義函數3.調用函數4.函數實現登錄案例5.函數的返回值 三、模塊和包1.模塊的概念(Module)2.模…

Linux中的shell腳本練習

1.判斷字符串是否為空 #!/usr/bin/bash while : #:默認值為真 do read -p "請輸入你的密碼: " a pass123456 if [ -z $a ];thenecho "您輸入的密碼不能為空"exit 1 elseif [ $a $pass ];thenecho "登錄成功"breakelseecho "您的密碼輸入有…

使用命令關閉Redis服務端

使用命令關閉Redis服務端。 命令 redis-cli -a 111111 -p 6379 shutdown 有些人redis的端口不是6379&#xff0c;那就自己查一下 參數解釋&#xff1a; -a&#xff1a;Redis密碼 -p&#xff1a;Redis端口 shutdown&#xff1a;關閉命令

嵌入式RTOS實戰:uC/OS-III最新版移植指南(附項目源碼)

文章目錄 前言一、uC/OS簡介二、工程移植2.1 下載ucos源碼2.2 創建空白工程2.3 拷貝ucosiii源碼文件2.3.1 UC-CONFIG2.3.2 UC-CPU2.3.3 UC-LIB2.3.4 UC-OS3 2.3 添加工程文件分組及路徑2.4 代碼首次編譯2.5 源碼修改2.5.1 cpu_cfg.h2.5.2 os_cpu_c.c2.5.3 lib_cfg.h2.5.4 sys.h…

TypeScript中的函數類型定義與類型約束

函數類型定義與類型約束 一、核心概念&#xff1a;類型別名與函數類型 1. 類型別名&#xff08;Type Alias&#xff09; 定義 類型別名使用 type 關鍵字為現有類型創建一個新名稱&#xff0c;可以用于&#xff1a; 基礎類型&#xff08;如 string、number&#xff09;&…

相機DreamCamera2錄像模式適配尺寸

在開發中遇到 一個問題&#xff0c;相機切換視頻模式時&#xff0c;預覽時&#xff0c;界面不能充滿屏幕兩側有黑邊&#xff0c;客戶要求修改&#xff0c;在此記錄 一問題現象&#xff1a; 系統相機在視頻模式下預覽時如下現象如圖1&#xff0c;期望現象如圖2: 圖1 …

SpringCloud組件——Gateway

一.網關 1.問題提出 我們通過Eureka&#xff0c;Nacos解決了服務注冊&#xff0c;服務發現的問題&#xff0c;使用SpringCloud LoadBalance解決了負載均衡的問題&#xff0c;使用OpenFeign解決了遠程調用的問題。 但是當前所有微服務的接口都是直接對外暴露的&#xff0c;可…

C#中構造器及屬性的加載順序

一.基本原則: 先加載靜態構造函數和靜態字段,后加載普通構造函數和普通字段;先加載基類再加載子類; 二.具體的加載順序: 父類靜態字段--->父類靜態構造函數--->子類靜態字段--->子類靜態構造函數--->父類實例字段---> 父類實例構造函數--->子類實例字段-…

Python面試問題

一、Python 基礎 1. Python 的特點 動態類型&#xff1a;變量無需聲明類型。解釋型語言&#xff1a;逐行解釋執行。支持多種編程范式&#xff08;面向對象、函數式、過程式&#xff09;。 2. 列表&#xff08;List&#xff09;與元組&#xff08;Tuple&#xff09;的區別 特…

計算機視覺進化論:YOLOv12、YOLOv11與Darknet系YOLOv7的微調實戰對比

摘要 YOLO系列作為實時目標檢測領域的重要里程碑&#xff0c;持續引領速度與精度的平衡發展。本文圍繞YOLOv7&#xff08;基于Darknet框架&#xff09;、YOLOv11及YOLOv12&#xff0c;系統、深入地對比了三款模型的架構創新、微調策略、核心技術及應用場景。我們詳細解析了三者…

SQL Server 存儲過程開發規范

SQL Server 存儲過程開發規范&#xff08;高級版&#xff09; 1. 總則 1.1 目標 本規范旨在&#xff1a; 提高存儲過程的事務一致性、異常可追蹤性、錯誤透明度。 統一日志記錄、錯誤碼管理、鏈路追蹤&#xff08;Trace ID&#xff09;。 支持復雜事務場景&#xff08;嵌套…

opendds的配置

配置的使用 文檔中說明有4種使用配置的方式&#xff1a; 環境變量 命令行參數&#xff08;將覆蓋環境變量中的配置&#xff09; 配置文件&#xff08;不會覆蓋環境變量或命令行參數中的配置&#xff09; 用戶調用的 API&#xff08;將覆蓋現有配置&#xff09; 這里對開發…

(Go Gin)上手Go Gin 基于Go語言開發的Web框架,本文介紹了各種路由的配置信息;包含各場景下請求參數的基本傳入接收

1. 路由 gin 框架中采用的路優酷是基于httprouter做的 HttpRouter 是一個高性能的 HTTP 請求路由器&#xff0c;適用于 Go 語言。它的設計目標是提供高效的路由匹配和低內存占用&#xff0c;特別適合需要高性能和簡單路由的應用場景。 主要特點 顯式匹配&#xff1a;與其他路由…