近期工作中需要完成一个基于局域网的双人联机游戏原型,游戏中需要两个客户端同步随机结果。由于只是展示用的原型,不需要校验,故我决定使用随机数种子保证随机的结果一致,在进入游戏时使用同个种子初始化。
我写了个简单的测试脚本进行测试,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RandomTest : MonoBehaviour
{
public Text txtLog;
private float timer = 0f;
private int count = 0;
private int seedIdx = 0;
private int[] SeedArr = new int[10] { 19971017, 19971105, 1, 337845818, 27, 64, 2, 888, 666, 7 };
private int[] minArr = new int[10] { 0, 1, 0, 2, 1, 0, 3, 1, 0, 0 };
private int[] maxArr = new int[10] { 1, 10, 0, 3, 4, 10, 9, 999, 9999, 1 };
void Start()
{
txtLog.text = "";
InitSeed();
}
void Update()
{
timer += Time.deltaTime;
if (timer >= 1f)
{
timer -= 1f;
ShowRandomNum();
}
}
private void InitSeed()
{
txtLog.text += $"重设随机种子为{SeedArr[seedIdx % 10]}\n";
Random.InitState(SeedArr[seedIdx % 10]);
seedIdx++;
}
private void ShowRandomNum()
{
count++;
int rangeIdx = (count - 1) % 10;
if (count % 5 == 0)
{
InitSeed();
}
int r = Random.Range(minArr[rangeIdx], maxArr[rangeIdx]);
Debug.Log($"第{count}次随机,随机范围:({minArr[rangeIdx]},{maxArr[rangeIdx]}), 数值为{r}");
txtLog.text = txtLog.text + r.ToString() + "\n";
}
}
代码会根据写死在数组里的数值定期重设随机数种子,每隔1秒会根据数组中配置的随机范围去随机一个int值。这样,每个客户端第n次随机的范围、种子都是一致的,也就模拟了原型中同步随机结果的需求。(由于每次随机相关操作是每个客户端都会执行的,所以在不需要校验的原型项目中,可视为所有客户端每次随机的范围一致。)
打包、双开测试效果如图: 结论:当使用 UnityEngine.Random 类的 InitState(int seed);方法后,不同客户端的同一次、同范围的随机结果是相同的。
正式项目中也可由服务器发给同一场游戏的每个客户端同个随机数种子,这样每个客户端的“演出”结果就可保证一致。
如有漏洞或错误,欢迎讨论、指正。
(至此的测试结果已经能满足我的简单需求,稍后可能会进行更全面的测试。)
|