该项目的目的是同时测试和演示来自 Unity DOTS 技术堆栈的多个新包。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

243 行
8.9 KiB

using System;
using Unity.Sample.Core;
using UnityEngine;
public struct DeltaReader
{
static byte[] fieldsNotPredicted = new byte[(NetworkConfig.maxFieldsPerSchema + 7) / 8];
unsafe public static int Read<TInputStream>(ref TInputStream input, NetworkSchema schema, uint[] outputData, uint[] baselineData, byte[] fieldsChangedPrediction, byte fieldMask, ref uint hash) where TInputStream : NetworkCompression.IInputStream
{
GameDebug.Assert(baselineData != null);
var index = 0;
int numFields = schema.numFields;
int skipContext = schema.id * NetworkConfig.maxContextsPerSchema + NetworkConfig.firstSchemaContext;
for (int i = 0; i * 8 < numFields; i++)
{
uint value = input.ReadPackedNibble(skipContext + 2 * i + 0);
value |= input.ReadPackedNibble(skipContext + 2 * i + 1) << 4;
fieldsNotPredicted[i] = (byte)(value ^ fieldsChangedPrediction[i]);
}
for (int i = 0; i < numFields; ++i)
{
var field = schema.fields[i];
GameDebug.Assert(field.byteOffset == index * 4);
int fieldStartContext = field.startContext;
byte fieldByteOffset = (byte)((uint)i >> 3);
byte fieldBitOffset = (byte)((uint)i & 0x7);
bool skip = (fieldsNotPredicted[fieldByteOffset] & (1 << fieldBitOffset)) == 0;
bool masked = ((field.fieldMask & fieldMask) != 0);
skip = skip || masked;
switch (field.fieldType)
{
case NetworkSchema.FieldType.Bool:
{
uint value = baselineData[index];
if (!skip)
value = input.ReadRawBits(1);
if (!masked)
hash = NetworkUtils.SimpleHashStreaming(hash, value);
outputData[index] = value;
index++;
break;
}
case NetworkSchema.FieldType.UInt:
case NetworkSchema.FieldType.Int:
case NetworkSchema.FieldType.Float:
{
uint baseline = (uint)baselineData[index];
uint value = baseline;
if (!skip)
{
if (field.delta)
{
value = input.ReadPackedUIntDelta(baseline, fieldStartContext);
}
else
{
value = input.ReadRawBits(field.bits);
}
}
if (!masked)
hash = NetworkUtils.SimpleHashStreaming(hash, value);
outputData[index] = value;
index++;
break;
}
case NetworkSchema.FieldType.Vector2:
{
uint bx = baselineData[index];
uint by = baselineData[index + 1];
uint vx = bx;
uint vy = by;
if (!skip)
{
if (field.delta)
{
vx = input.ReadPackedUIntDelta(bx, fieldStartContext + 0);
vy = input.ReadPackedUIntDelta(by, fieldStartContext + 1);
}
else
{
vx = input.ReadRawBits(field.bits);
vy = input.ReadRawBits(field.bits);
}
}
if (!masked)
{
hash = NetworkUtils.SimpleHashStreaming(hash, vx);
hash = NetworkUtils.SimpleHashStreaming(hash, vy);
}
outputData[index] = vx;
outputData[index + 1] = vy;
index += 2;
break;
}
case NetworkSchema.FieldType.Vector3:
{
uint bx = baselineData[index];
uint by = baselineData[index + 1];
uint bz = baselineData[index + 2];
uint vx = bx;
uint vy = by;
uint vz = bz;
if (!skip)
{
if (field.delta)
{
vx = input.ReadPackedUIntDelta(bx, fieldStartContext + 0);
vy = input.ReadPackedUIntDelta(by, fieldStartContext + 1);
vz = input.ReadPackedUIntDelta(bz, fieldStartContext + 2);
}
else
{
vx = input.ReadRawBits(field.bits);
vy = input.ReadRawBits(field.bits);
vz = input.ReadRawBits(field.bits);
}
}
if (!masked)
{
hash = NetworkUtils.SimpleHashStreaming(hash, vx);
hash = NetworkUtils.SimpleHashStreaming(hash, vy);
hash = NetworkUtils.SimpleHashStreaming(hash, vz);
}
outputData[index] = vx;
outputData[index + 1] = vy;
outputData[index + 2] = vz;
index += 3;
break;
}
case NetworkSchema.FieldType.Quaternion:
{
uint bx = baselineData[index];
uint by = baselineData[index + 1];
uint bz = baselineData[index + 2];
uint bw = baselineData[index + 3];
uint vx = bx;
uint vy = by;
uint vz = bz;
uint vw = bw;
if (!skip)
{
if (field.delta)
{
vx = input.ReadPackedUIntDelta(bx, fieldStartContext + 0);
vy = input.ReadPackedUIntDelta(by, fieldStartContext + 1);
vz = input.ReadPackedUIntDelta(bz, fieldStartContext + 2);
vw = input.ReadPackedUIntDelta(bw, fieldStartContext + 3);
//RUTODO: normalize
}
else
{
vx = input.ReadRawBits(field.bits);
vy = input.ReadRawBits(field.bits);
vz = input.ReadRawBits(field.bits);
vw = input.ReadRawBits(field.bits);
}
}
if (!masked)
{
hash = NetworkUtils.SimpleHashStreaming(hash, vx);
hash = NetworkUtils.SimpleHashStreaming(hash, vy);
hash = NetworkUtils.SimpleHashStreaming(hash, vz);
hash = NetworkUtils.SimpleHashStreaming(hash, vw);
}
outputData[index] = vx;
outputData[index + 1] = vy;
outputData[index + 2] = vz;
outputData[index + 3] = vw;
index += 4;
break;
}
case NetworkSchema.FieldType.String:
case NetworkSchema.FieldType.ByteArray:
{
// TODO : Do a better job with deltaing strings and buffers
if (!skip)
{
uint count = input.ReadPackedUInt(fieldStartContext);
outputData[index] = count;
index++;
fixed(uint* buf = outputData)
{
byte* dst = (byte*)(buf + index);
int idx = 0;
for (; idx < count; ++idx)
*dst++ = (byte)input.ReadRawBits(8);
for (; idx < field.arraySize / 4; ++idx)
*dst++ = 0;
}
index += field.arraySize / 4;
}
else
{
for (int idx = 0, c = field.arraySize / 4; idx < c; ++idx)
outputData[index + idx] = baselineData[index + idx];
index += field.arraySize / 4 + 1;
}
if (!masked)
{
hash += 0; // TODO (hash strings and bytearrays as well)
}
}
break;
}
}
return index * 4;
}
}