Add AIServer, character art pipeline, and Art package boot integration.
Bring in MaleExplorer assets/shaders, model tooling and Hunyuan updates, plus boot/YooAsset Art package support. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
using System.Collections;
|
||||
using AOT.Boot;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace HotUpdate
|
||||
{
|
||||
/// <summary>
|
||||
/// M3:加载示例角色 MaleExplorer 进场景。
|
||||
/// </summary>
|
||||
public sealed class CharacterSpawner : MonoBehaviour
|
||||
{
|
||||
public const string PrefabAddress = "MaleExplorer";
|
||||
public const string EditorPrefabPath = "Assets/Bundles/Characters/MaleExplorer/MaleExplorer.prefab";
|
||||
public const string ArtPackageName = "Art";
|
||||
|
||||
BootContext _ctx;
|
||||
GameObject _instance;
|
||||
|
||||
public void Bind(BootContext ctx) => _ctx = ctx;
|
||||
|
||||
public void Spawn()
|
||||
{
|
||||
StartCoroutine(SpawnCo());
|
||||
}
|
||||
|
||||
IEnumerator SpawnCo()
|
||||
{
|
||||
GameObject prefab = null;
|
||||
|
||||
// 1) YooAsset Art 包(Offline/Host 已初始化时)
|
||||
if (YooAssets.IsInitialized && YooAssets.TryGetPackage(ArtPackageName, out var art) &&
|
||||
art.InitializeStatus == EOperationStatus.Succeeded)
|
||||
{
|
||||
var handle = art.LoadAssetAsync<GameObject>(PrefabAddress);
|
||||
yield return handle;
|
||||
if (handle.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
prefab = handle.GetAssetObject<GameObject>();
|
||||
Debug.Log($"[CharacterSpawner] loaded from YooAsset Art address={PrefabAddress}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[CharacterSpawner] Art load failed: {handle.Error}");
|
||||
handle.Release();
|
||||
}
|
||||
}
|
||||
|
||||
// 2) 编辑器直通:AssetDatabase
|
||||
#if UNITY_EDITOR
|
||||
if (prefab == null)
|
||||
{
|
||||
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(EditorPrefabPath);
|
||||
if (prefab != null)
|
||||
Debug.Log($"[CharacterSpawner] loaded via AssetDatabase {EditorPrefabPath}");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (prefab == null)
|
||||
{
|
||||
Debug.LogError("[CharacterSpawner] MaleExplorer prefab not found");
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (_instance != null)
|
||||
Destroy(_instance);
|
||||
|
||||
_instance = Instantiate(prefab);
|
||||
_instance.name = "MaleExplorer_Runtime";
|
||||
_instance.transform.position = new Vector3(0f, 0f, 2.5f);
|
||||
DontDestroyOnLoad(_instance);
|
||||
|
||||
// 简易朝向相机
|
||||
var billboard = _instance.GetComponentInChildren<MeshRenderer>();
|
||||
if (billboard != null && Camera.main != null)
|
||||
{
|
||||
var t = billboard.transform;
|
||||
var cam = Camera.main.transform;
|
||||
var dir = cam.position - t.position;
|
||||
dir.y = 0f;
|
||||
if (dir.sqrMagnitude > 0.001f)
|
||||
t.rotation = Quaternion.LookRotation(-dir.normalized);
|
||||
}
|
||||
|
||||
// 调整主相机看向角色(竖屏)
|
||||
if (Camera.main != null)
|
||||
{
|
||||
var cam = Camera.main;
|
||||
cam.transform.position = new Vector3(0f, 1.4f, -1.2f);
|
||||
cam.transform.rotation = Quaternion.Euler(8f, 0f, 0f);
|
||||
cam.fieldOfView = 50f;
|
||||
cam.backgroundColor = new Color(0.45f, 0.62f, 0.78f);
|
||||
}
|
||||
|
||||
Debug.Log($"[CharacterSpawner] spawned ok res={_ctx?.ResVersion}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cd65ba42ca5feb4b9912b12d3edb8c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -36,6 +36,11 @@ namespace HotUpdate
|
||||
Debug.Log($"[HotUpdate] Bootstrap ready. CDN={_ctx?.CdnRoot}");
|
||||
EnsureHud();
|
||||
|
||||
// M3:示例角色(与网络并行,不依赖 WS)
|
||||
var spawner = gameObject.AddComponent<CharacterSpawner>();
|
||||
spawner.Bind(_ctx);
|
||||
spawner.Spawn();
|
||||
|
||||
_net = gameObject.AddComponent<GameNet>();
|
||||
_net.Bind(_ctx);
|
||||
_net.OnStatus += s =>
|
||||
@@ -45,7 +50,7 @@ namespace HotUpdate
|
||||
_net.OnWsReady += () =>
|
||||
{
|
||||
if (_hud != null)
|
||||
_hud.text = $"WS OK pid={_net.Session?.Pid}";
|
||||
_hud.text = $"WS OK pid={_net.Session?.Pid} | MaleExplorer";
|
||||
Debug.Log($"[HotUpdate] M2 WS ready pid={_net.Session?.Pid}");
|
||||
};
|
||||
_net.StartGuestSession();
|
||||
|
||||
@@ -28,7 +28,12 @@ namespace HotUpdate.Net
|
||||
public void Bind(BootContext boot)
|
||||
{
|
||||
_boot = boot;
|
||||
if (_boot != null && !string.IsNullOrEmpty(_boot.WsUrlTemplate))
|
||||
if (_boot == null) return;
|
||||
|
||||
if (!string.IsNullOrEmpty(_boot.HttpBase))
|
||||
HttpBase = _boot.HttpBase;
|
||||
|
||||
if (!string.IsNullOrEmpty(_boot.WsUrlTemplate))
|
||||
{
|
||||
// 旧模板只有 pid 时补上 token
|
||||
var tpl = _boot.WsUrlTemplate;
|
||||
|
||||
Reference in New Issue
Block a user