add:添加中控控制脚本

This commit is contained in:
bzx
2026-01-14 19:03:11 +08:00
parent 338d42e8ac
commit f3f8a04931
7 changed files with 397 additions and 4 deletions

View File

@@ -4692,9 +4692,11 @@ MonoBehaviour:
- {fileID: 399455311}
enemyPos: {fileID: 1152711581}
startDoorPos: {fileID: 928594070}
aiPos: {fileID: 0}
self: {fileID: 0}
Version: 1.0.1
place: 0
gameId: 0
--- !u!1 &399455311
GameObject:
m_ObjectHideFlags: 0
@@ -24361,6 +24363,50 @@ MonoBehaviour:
soundPlayedCustomEvent:
willCleanUpDelegatesAfterStop: 1
frames: 178
--- !u!1 &1830913919
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1830913920}
- component: {fileID: 1830913921}
m_Layer: 0
m_Name: HttpServer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1830913920
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1830913919}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2085135536}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1830913921
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1830913919}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: da420a9230298754b8b457b69fc650c2, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1859816369
GameObject:
m_ObjectHideFlags: 0
@@ -26917,6 +26963,7 @@ Transform:
m_Children:
- {fileID: 1817525541}
- {fileID: 471696836}
- {fileID: 1830913920}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2086780501

View File

@@ -5,6 +5,21 @@ using DarkTonic.MasterAudio;
using Unity.XR.PXR;
using UnityEngine;
public enum GameKey
{
DinosaurPark2=0,//重返侏罗纪
SpongeBob=1,//深海冒险
XMen=2,//银河守护者
KOF=3,//幻影交锋
Valheim=4,//小小幻宠
FutureMen=5,//未来战警
AliceBall=6,//爱丽丝的舞会
Zombie=7,//僵尸来了
DefendNJ=8,//保卫金陵
Loong=9, //巨龙猎人
MRCS=10,//火力对决
SXDMystery=11,//三星堆之谜
}
public enum Place
{
Company1Floor=0,
@@ -106,10 +121,13 @@ public class GameLocal : MonoBehaviour
[Header("场地")]
public Place place = Place.Company1Floor;
public GameKey gameId;
void Start()
{
Ins = this;
Application.targetFrameRate = 60;
gameId = GameKey.AliceBall;
AuthorPanel.Show();
foreach (var item in BGM)
{
@@ -178,7 +196,7 @@ public class GameLocal : MonoBehaviour
authInfo.shop = 44;
#endif
authInfo.gameId = 6;
authInfo.gameId = (int)gameId;
string authJson = JsonUtility.ToJson(authInfo);
Debug.Log("发送数据 -> " + authJson);
request.RawData = System.Text.Encoding.UTF8.GetBytes(authJson);

View File

@@ -44,6 +44,7 @@ public class GameManager : MonoBehaviour
public GameState gameState;
public float vistEnd = 60 * 10;
public float curGameTime = 0;
public GameObject wuHui;
@@ -393,6 +394,15 @@ public class GameManager : MonoBehaviour
//}
//更新指引箭头位置
UpdateGuideArrowPosition();
if (gameState == GameState.Playing)
{
curGameTime+=Time.deltaTime;
}
}
public int GetNowTime()
{
return Mathf.RoundToInt(curGameTime);
}
#region

View File

@@ -0,0 +1,305 @@
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
using UnityEngine;
using Valheim;
[Serializable]
public class IntentMessage
{
public string intent;
}
[Serializable]
public class PlayingStatusResponse
{
public int code;
public ServerData data;
public string message;
}
[Serializable]
public class ServerData
{
public string gameName;
public int gameTotalTime;
public int currentPlayTime;
}
public class HttpServer : MonoBehaviour
{
private HttpListener listener;
private Thread serverThread;
private volatile bool isRunning;
private const string SERVER_URL = "http://+:12345/";
// 子线程 → 主线程
private static ConcurrentQueue<NetMessage> messageQueue = new ConcurrentQueue<NetMessage>();
void Awake()
{
DontDestroyOnLoad(gameObject);
}
void Start()
{
StartServer();
}
#region HTTP Server
private void StartServer()
{
try
{
listener = new HttpListener();
listener.Prefixes.Add(SERVER_URL);
listener.Start();
isRunning = true;
serverThread = new Thread(ListenLoop)
{
IsBackground = true
};
serverThread.Start();
Debug.Log($"✅ HTTP Server 启动成功:{SERVER_URL}");
}
catch (Exception e)
{
Debug.LogError("❌ HTTP Server 启动失败:" + e);
}
}
private void ListenLoop()
{
while (isRunning && listener.IsListening)
{
try
{
var context = listener.GetContext();
ThreadPool.QueueUserWorkItem(ProcessRequest, context);
}
catch (HttpListenerException)
{
break;
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
private void ProcessRequest(object state)
{
var context = (HttpListenerContext)state;
var request = context.Request;
var response = context.Response;
response.AddHeader("Access-Control-Allow-Origin", "*");
response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.AddHeader("Access-Control-Allow-Headers", "Content-Type");
response.ContentType = "application/json; charset=utf-8";
try
{
if (request.HttpMethod == "POST")
{
string raw;
using (var reader = new StreamReader(
request.InputStream,
request.ContentEncoding ?? Encoding.UTF8))
{
raw = reader.ReadToEnd();
}
Debug.Log($"📩 收到原始 JSON{raw}");
// 解析 intent
IntentMessage intentMsg = null;
try
{
intentMsg = JsonUtility.FromJson<IntentMessage>(raw);
}
catch (Exception e)
{
Debug.LogError("JSON 解析失败:" + e);
}
// 只处理 is_playing
if (intentMsg != null && intentMsg.intent == "is_playing")
{
var resp = new PlayingStatusResponse
{
code = 200,
data = new ServerData()
{
gameName = GetCurrentGameName(),
gameTotalTime = GetGameTotalTime(),
currentPlayTime = GetCurrentPlayTime()
},
message = "请求成功"
};
string json = JsonUtility.ToJson(resp);
byte[] data = Encoding.UTF8.GetBytes(json);
response.OutputStream.Write(data, 0, data.Length);
}
else
{
// 未知 intent
string err = "{\"code\":400,\"msg\":\"unknown intent\"}";
byte[] data = Encoding.UTF8.GetBytes(err);
response.OutputStream.Write(data, 0, data.Length);
}
response.Close();
return;
}
}
catch (Exception e)
{
Debug.LogError(e);
WriteResponse(response, 500, "error");
}
finally
{
response.Close();
}
}
private void WriteResponse(HttpListenerResponse response, int code, string msg)
{
string json = $"{{\"code\":{code},\"msg\":\"{msg}\"}}";
byte[] data = Encoding.UTF8.GetBytes(json);
response.OutputStream.Write(data, 0, data.Length);
}
#endregion
#region Unity Main Thread
void Update()
{
while (messageQueue.TryDequeue(out var msg))
{
Debug.Log($"📩 来自 [{msg.sender}] 指令 [{msg.command}]");
HandleMessage(msg);
}
}
#endregion
#region Message Logic
[Serializable]
public class NetMessage
{
public string sender;
public string command;
}
private NetMessage ParseMessage(string raw)
{
if (string.IsNullOrEmpty(raw))
return null;
try
{
raw = raw.Replace("\"", "").Trim();
var parts = raw.Split(':');
if (parts.Length != 2)
{
Debug.LogWarning($"消息格式错误:{raw}");
return null;
}
return new NetMessage
{
sender = parts[0].Trim(),
command = parts[1].Trim()
};
}
catch (Exception e)
{
Debug.LogError($"解析失败:{raw}\n{e}");
return null;
}
}
private void HandleMessage(NetMessage msg)
{
switch (msg.command)
{
case "isStart":
OnStartCommand(msg.sender);
break;
default:
Debug.LogWarning($"未知指令:{msg.command}");
break;
}
}
private void OnStartCommand(string sender)
{
Debug.Log($"🚀 Start 指令来自:{sender}");
// ✅ 在这里安全调用 Unity API
// GameManager.Ins.QuitGame();
}
private string GetCurrentGameName()
{
return GameLocal.Ins.gameId.ToString(); // 或你自己的 GameManager
}
private int GetGameTotalTime()
{
return Mathf.FloorToInt(GameManager.Ins.vistEnd); // 举例1 小时(秒)
}
private int GetCurrentPlayTime()
{
return GameManager.Ins.GetNowTime();
}
#endregion
#region Shutdown
void OnDestroy()
{
StopServer();
}
private void StopServer()
{
isRunning = false;
try
{
listener?.Stop();
listener?.Close();
}
catch { }
try
{
if (serverThread != null && serverThread.IsAlive)
serverThread.Join(300);
}
catch { }
Debug.Log("🛑 HTTP Server 已关闭");
}
#endregion
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da420a9230298754b8b457b69fc650c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -5,7 +5,7 @@ EditorBuildSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Scenes:
- enabled: 0
- enabled: 1
path: Assets/_Alice/Scenes/GongSi1Lou.unity
guid: 86606d278f928a542a15d123d4ad5829
- enabled: 0
@@ -194,7 +194,7 @@ EditorBuildSettings:
- enabled: 0
path: Assets/_Alice/Scenes/Shandong_Weifang_Linqu_WandaGuangchang_Shinei.unity
guid: 8a7f0a8b1a9335f44a3f80dcd50f6763
- enabled: 1
- enabled: 0
path: Assets/_Alice/Scenes/Liaoning_Panjin_Shuangtaizi_Shuangtaicheng.unity
guid: d8a7add0386eeff489089f0411d70b5a
m_configObjects:

View File

@@ -142,7 +142,9 @@ PlayerSettings:
visionOSBundleVersion: 1.0
tvOSBundleVersion: 1.0
bundleVersion: 1.0.2
preloadedAssets: []
preloadedAssets:
- {fileID: 11400000, guid: d0f8149c48842b4488cf6fb974cff9a2, type: 2}
- {fileID: 1814176829808956018, guid: 58f40b12bbc864f3c96c6505a9a1e1e3, type: 2}
metroInputSource: 0
wsaTransparentSwapchain: 0
m_HolographicPauseOnTrackingLoss: 1