浏览代码

Updated to 12194

/main
Peter Andreasen 5 年前
当前提交
f97019fe
共有 33 个文件被更改,包括 207 次插入100 次删除
  1. 13
      Assets/Scripts/Game/Entity/GameWorld.cs
  2. 30
      Assets/Scripts/Game/Main/ClientGameLoop.cs
  3. 1
      Assets/Scripts/Game/Main/ServerGameLoop.cs
  4. 1
      Assets/Scripts/Game/Main/ThinClientGameLoop.cs
  5. 2
      Assets/Scripts/Game/Modules/Character/Components/CharacterInterpolated.cs
  6. 2
      Assets/Scripts/Game/Modules/Character/Components/CharacterPredicted.cs
  7. 2
      Assets/Scripts/Game/Modules/Character/Components/CharacterReplicated.cs
  8. 1
      Assets/Scripts/Game/Modules/Effect/VFXSystem.cs
  9. 2
      Assets/Scripts/Game/Modules/HitCollision/HitCollisionOwner.cs
  10. 2
      Assets/Scripts/Game/Modules/Player/Components/UserCommandComponent.cs
  11. 2
      Assets/Scripts/Game/Modules/Presentation/PresentationOwner.cs
  12. 2
      Assets/Scripts/Game/Modules/Ragdoll/RagdollState.cs
  13. 2
      Assets/Scripts/Game/Modules/ReplicatedEntity/ReplicatedEntity.cs
  14. 2
      Assets/Scripts/Game/Modules/SpectatorCam/SpectatorCam.cs
  15. 2
      Assets/Scripts/Game/Systems/Damage/DamageHistory.cs
  16. 2
      Assets/Scripts/Game/Systems/Damage/HealthState.cs
  17. 2
      Assets/Scripts/Game/Systems/DestructibleProp/DestructablePropReplicatedState.cs
  18. 2
      Assets/Scripts/Game/Systems/Movable/Movable.cs
  19. 2
      Assets/Scripts/Game/Systems/Teleporter/Components/TeleporterPresentation.cs
  20. 91
      Assets/Scripts/Networking/Matchmaking/Matchmaker.cs
  21. 4
      Assets/Scripts/Networking/Matchmaking/MatchmakingClient.cs
  22. 10
      Assets/Scripts/Networking/Matchmaking/MatchmakingClient.cs.meta
  23. 14
      Assets/Scripts/Networking/Matchmaking/MatchmakingController.cs
  24. 10
      Assets/Scripts/Networking/Matchmaking/MatchmakingController.cs.meta
  25. 10
      Assets/Scripts/Networking/Matchmaking/MatchmakingCustomProperties.cs.meta
  26. 27
      Assets/Scripts/Networking/Matchmaking/MatchmakingModel.cs
  27. 10
      Assets/Scripts/Networking/Matchmaking/MatchmakingModel.cs.meta
  28. 27
      CHANGELOG.md
  29. 4
      Packages/manifest.json
  30. 6
      ProjectSettings/EditorSettings.asset
  31. 6
      ProjectSettings/ProjectSettings.asset
  32. 2
      ProjectSettings/ProjectVersion.txt
  33. 12
      README.md

13
Assets/Scripts/Game/Entity/GameWorld.cs


m_sceneRoot = new GameObject(name);
GameObject.DontDestroyOnLoad(m_sceneRoot);
}
m_ECSWorld = World.Active != null ? World.Active : new World(name);
World.Active = m_ECSWorld;
GameDebug.Assert(World.Active != null,"There is no active world");
m_ECSWorld = World.Active;
m_EntityManager = m_ECSWorld.GetOrCreateManager<EntityManager>();

ProcessDespawns();
s_Worlds.Remove(this);
if (m_ECSWorld.IsCreated)
{
m_ECSWorld.Dispose();
m_ECSWorld = null;
World.Active = null;
}
GameObject.Destroy(m_sceneRoot);
}

30
Assets/Scripts/Game/Main/ClientGameLoop.cs


#if UNITY_EDITOR
Game.game.levelManager.UnloadLevel();
World.DisposeAllWorlds();
#endif
m_GameWorld = new GameWorld("ClientWorld");

if (string.IsNullOrEmpty(endpoint))
{
GameDebug.LogError("matchmake: command requires an endpoint <hostname[:port]/{projectid}>");
GameDebug.LogError("matchmake: command requires an endpoint <ex: cloud.connected.unity3d.com/{projectid}>");
return;
}

return;
}
GameDebug.Log($"matchmake: Starting the matchmaker. Requesting match from {endpoint} for player {clientPlayerName.Value}.");
GameDebug.Log($"matchmake: Starting the matchmaker. Requesting match from {endpoint} for request ID {clientPlayerName.Value}.");
m_matchmaker = new Matchmaker(endpoint);
m_matchmaker = new Matchmaker(endpoint, OnMatchmakingSuccess, OnMatchmakingError);
MatchmakingRequest request = Matchmaker.CreateMatchmakingRequest(clientPlayerName.Value, playerProps, groupProps);
m_matchmaker.RequestMatch(request, OnMatchmakingSuccess, OnMatchmakingError);
m_matchmaker.RequestMatch(clientPlayerName.Value, playerProps, groupProps);
void OnMatchmakingSuccess(string connectionInfo)
void OnMatchmakingSuccess(Assignment assignment)
GameDebug.Log($"Matchmaking has found a game! The server is at: {connectionInfo}");
// TODO: Uncomment following line when matchmaking service returns an endpoint instead of the roster
//Console.EnqueueCommand($"connect {connectionInfo}");
if (string.IsNullOrEmpty(assignment.ConnectionString))
{
GameDebug.Log("Matchmaking finished, but did not return a game server. Ensure your server has been allocated and is running then try again.");
GameDebug.Log($"MM Error: {assignment.AssignmentError ?? "None"}");
}
else
{
GameDebug.Log($"Matchmaking has found a game! The server is at {assignment.ConnectionString}. Attempting to connect...");
Console.EnqueueCommand($"connect {assignment.ConnectionString}");
}
m_useMatchmaking = false;
m_matchmaker = null;
}

m_useMatchmaking = false;
m_matchmaker = null;
}

1
Assets/Scripts/Game/Main/ServerGameLoop.cs


#if UNITY_EDITOR
Game.game.levelManager.UnloadLevel();
World.DisposeAllWorlds();
#endif
m_GameWorld = new GameWorld("ServerWorld");

1
Assets/Scripts/Game/Main/ThinClientGameLoop.cs


#if UNITY_EDITOR
Game.game.levelManager.UnloadLevel();
World.DisposeAllWorlds();
#endif
Console.AddCommand("disconnect", CmdDisconnect, "Disconnect from server if connected", this.GetHashCode());

2
Assets/Scripts/Game/Modules/Character/Components/CharacterInterpolated.cs


}
}
public class CharacterInterpolated : ComponentDataWrapper<CharacterInterpolatedData>
public class CharacterInterpolated : ComponentDataProxy<CharacterInterpolatedData>
{}

2
Assets/Scripts/Game/Modules/Character/Components/CharacterPredicted.cs


#endif
}
public class CharacterPredicted : ComponentDataWrapper<CharacterPredictedData>
public class CharacterPredicted : ComponentDataProxy<CharacterPredictedData>
{}

2
Assets/Scripts/Game/Modules/Character/Components/CharacterReplicated.cs


}
}
public class CharacterReplicated : ComponentDataWrapper<CharacterReplicatedData>
public class CharacterReplicated : ComponentDataProxy<CharacterReplicatedData>
{
}

1
Assets/Scripts/Game/Modules/Effect/VFXSystem.cs


using UnityEngine;
using UnityEngine.Experimental.VFX;
[DisableAutoCreation]
public class VFXSystem : ComponentSystem
{
static readonly int positionID = Shader.PropertyToID("position");

2
Assets/Scripts/Game/Modules/HitCollision/HitCollisionOwner.cs


[DisallowMultipleComponent]
public class HitCollisionOwner : ComponentDataWrapper<HitCollisionOwnerData>
public class HitCollisionOwner : ComponentDataProxy<HitCollisionOwnerData>
{
private void OnEnable()
{

2
Assets/Scripts/Game/Modules/Player/Components/UserCommandComponent.cs


}
}
public class UserCommandComponent : ComponentDataWrapper<UserCommandComponentData>
public class UserCommandComponent : ComponentDataProxy<UserCommandComponentData>
{}

2
Assets/Scripts/Game/Modules/Presentation/PresentationOwner.cs


}
}
public class PresentationOwner : ComponentDataWrapper<PresentationOwnerData>
public class PresentationOwner : ComponentDataProxy<PresentationOwnerData>
{}

2
Assets/Scripts/Game/Modules/Ragdoll/RagdollState.cs


}
}
public class RagdollState : ComponentDataWrapper<RagdollStateData>
public class RagdollState : ComponentDataProxy<RagdollStateData>
{
}

2
Assets/Scripts/Game/Modules/ReplicatedEntity/ReplicatedEntity.cs


[ExecuteAlways, DisallowMultipleComponent]
[RequireComponent(typeof(GameObjectEntity))]
public class ReplicatedEntity : ComponentDataWrapper<ReplicatedEntityData>
public class ReplicatedEntity : ComponentDataProxy<ReplicatedEntityData>
{
public byte[] netID; // guid of instance. Used for identifying replicated entities from the scene

2
Assets/Scripts/Game/Modules/SpectatorCam/SpectatorCam.cs


public class SpectatorCam : ComponentDataWrapper<SpectatorCamData>
public class SpectatorCam : ComponentDataProxy<SpectatorCamData>
{
}

2
Assets/Scripts/Game/Systems/Damage/DamageHistory.cs


}
}
public class DamageHistory : ComponentDataWrapper<DamageHistoryData>
public class DamageHistory : ComponentDataProxy<DamageHistoryData>
{
}

2
Assets/Scripts/Game/Systems/Damage/HealthState.cs


}
public class HealthState : ComponentDataWrapper<HealthStateData>
public class HealthState : ComponentDataProxy<HealthStateData>
{
}

2
Assets/Scripts/Game/Systems/DestructibleProp/DestructablePropReplicatedState.cs


}
}
public class DestructablePropReplicatedState : ComponentDataWrapper<DestructablePropReplicatedData>
public class DestructablePropReplicatedState : ComponentDataProxy<DestructablePropReplicatedData>
{
}

2
Assets/Scripts/Game/Systems/Movable/Movable.cs


}
[RequireComponent(typeof(Rigidbody))]
public class Movable : ComponentDataWrapper<MovableData>
public class Movable : ComponentDataProxy<MovableData>
{
public void Start()
{

2
Assets/Scripts/Game/Systems/Teleporter/Components/TeleporterPresentation.cs


}
[DisallowMultipleComponent]
public class TeleporterPresentation : ComponentDataWrapper<TeleporterPresentationData>
public class TeleporterPresentation : ComponentDataProxy<TeleporterPresentationData>
{
}

91
Assets/Scripts/Networking/Matchmaking/Matchmaker.cs


namespace UnityEngine.Ucg.Matchmaking
{
public class Matchmaker
public class Matchmaker
/// The hostname[:port]/{projectid} for the running matchmaker assigned to this project
/// The hostname[:port]/{projectid} of your matchmaking server
MatchmakingRequest MatchmakingRequest;
public delegate void SuccessCallback(string connectionInfo);
private MatchmakingRequest request;
public delegate void SuccessCallback(Assignment assignment);
SuccessCallback m_Success;
ErrorCallback m_Error;
public SuccessCallback successCallback;
public ErrorCallback errorCallback;
public enum MatchmakingState
{

/// </summary>
public MatchmakingState State = MatchmakingState.None;
public Matchmaker(string endpoint)
/// <summary>
/// Matchmaker
/// </summary>
/// <param name="endpoint"></param>
/// <param name="onSuccessCallback">If a match is found, this callback will provide the connection information</param>
/// <param name="onErrorCallback">If matchmaking fails, this callback will provided some failure information</param>
public Matchmaker(string endpoint, SuccessCallback onSuccessCallback = null, ErrorCallback onErrorCallback = null)
this.successCallback = onSuccessCallback;
this.errorCallback = onErrorCallback;
}
/// <summary>
/// Start Matchmaking
/// </summary>
/// <param name="playerId">The id of the player</param>
/// <param name="playerProps">Custom player properties relevant to the matchmaking function</param>
/// <param name="groupProps">Custom group properties relevant to the matchmaking function</param>
public void RequestMatch(string playerId, MatchmakingPlayerProperties playerProps, MatchmakingGroupProperties groupProps)
{
request = CreateMatchmakingRequest(playerId, playerProps, groupProps);
matchmakingController = new MatchmakingController(Endpoint);
matchmakingController.StartRequestMatch(request, GetAssignment, OnError);
State = MatchmakingState.Requesting;
Debug.Log(State);
}
/// <summary>

break;
case MatchmakingState.Found:
case MatchmakingState.Error:
Debug.Log("Update() is still being called after matchmaking finished.");
break;
break; // User hasn't stopped the state machine yet.
default:
throw new ArgumentOutOfRangeException();
}

/// <param name="playerProps">Custom player properties relevant to the matchmaking function</param>
/// <param name="groupProps">Custom group properties relevant to the matchmaking function</param>
/// <returns></returns>
public static MatchmakingRequest CreateMatchmakingRequest(string playerId, MatchmakingPlayerProperties playerProps, MatchmakingGroupProperties groupProps)
private static MatchmakingRequest CreateMatchmakingRequest(string playerId, MatchmakingPlayerProperties playerProps, MatchmakingGroupProperties groupProps)
MatchmakingRequest request = new MatchmakingRequest();
MatchmakingPlayer thisPlayer = new MatchmakingPlayer(playerId);
// TODO: WORKAROUND: Currently matchmaker handles IDs as UUIDs, not player names, and will only ever generate 1 match assignment for each UUID
// Therefore, we'll append the current time in Ticks as an attempt at creating a UUID
playerId = playerId + DateTime.UtcNow.Ticks.ToString();
MatchmakingPlayer thisPlayer = new MatchmakingPlayer(playerId)
{
Properties = JsonUtility.ToJson(playerProps)
};
MatchmakingRequest request = new MatchmakingRequest()
{
Properties = JsonUtility.ToJson(groupProps)
};
thisPlayer.Properties = JsonUtility.ToJson(playerProps);
request.Properties = JsonUtility.ToJson(groupProps);
/// <summary>
/// Start matchmaking
/// </summary>
/// <param name="request">The matchmaking request</param>
/// <param name="successCallback">If a match is found, this callback will provide the connection information</param>
/// <param name="errorCallback">If matchmaking fails, this callback will provided some failure information</param>
public void RequestMatch(MatchmakingRequest request, SuccessCallback successCallback,
ErrorCallback errorCallback)
{
m_Success = successCallback;
m_Error = errorCallback;
MatchmakingRequest = request;
matchmakingController = new MatchmakingController(Endpoint);
matchmakingController.StartRequestMatch(request, GetAssignment, OnError);
State = MatchmakingState.Requesting;
Debug.Log(State);
}
matchmakingController.StartGetAssignment(MatchmakingRequest.Players[0].Id, OnSuccess, OnError);
matchmakingController.StartGetAssignment(request.Players[0].Id, OnSuccess, OnError);
void OnSuccess(string connectionInfo)
void OnSuccess(Assignment assignment)
m_Success.Invoke(connectionInfo);
successCallback?.Invoke(assignment);
}
void OnError(string error)

m_Error.Invoke(error);
errorCallback?.Invoke(error ?? "Undefined Error");
}
}

4
Assets/Scripts/Networking/Matchmaking/MatchmakingClient.cs


internal MatchmakingClient(string endpoint)
{
Url = "https://" + endpoint + "/matchmaking/api/v" + k_ApiVersion;
Url = "https://" + endpoint + "/api/v" + k_ApiVersion + "/matchmaking";
/// Start matchmaking for a provided request. This tells your matchmaking endpoint to add
/// Start matchmaking for a provided request. This tells your matchmaking endpoint to add
/// the players and group data in the request to the matchmaking pool for consideration
/// </summary>
/// <param name="request">The matchmaking request</param>

10
Assets/Scripts/Networking/Matchmaking/MatchmakingClient.cs.meta


fileFormatVersion: 2
guid: 852dde79476a4b8b83b8cf8642f41564
timeCreated: 1537222065
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

14
Assets/Scripts/Networking/Matchmaking/MatchmakingController.cs


{
public delegate void RequestMatchSuccess();
public delegate void RequestMatchError(string error);
public delegate void GetAssignmentSuccess(string connectionInfo);
public delegate void GetAssignmentSuccess(Assignment assignment);
public delegate void GetAssignmentError(string error);
RequestMatchSuccess m_RequestMatchSuccess;

return;
}
ConnectionInfo result = JsonUtility.FromJson<ConnectionInfo>(m_GetAssignmentOperation.webRequest.downloadHandler.text);
m_GetAssignmentSuccess.Invoke(result.ConnectionString);
Assignment result = JsonUtility.FromJson<Assignment>(m_GetAssignmentOperation.webRequest.downloadHandler.text);
if (!string.IsNullOrEmpty(result.AssignmentError))
{
m_GetAssignmentError.Invoke(result.AssignmentError);
return;
}
m_GetAssignmentSuccess.Invoke(result);
}
}
}

10
Assets/Scripts/Networking/Matchmaking/MatchmakingController.cs.meta


fileFormatVersion: 2
guid: a018dfdb8bd8435aaad8488dfaa3bde4
timeCreated: 1537222026
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

10
Assets/Scripts/Networking/Matchmaking/MatchmakingCustomProperties.cs.meta


fileFormatVersion: 2
guid: 4cb752d9dc8e4308bacedb984583e660
timeCreated: 1537226528
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

27
Assets/Scripts/Networking/Matchmaking/MatchmakingModel.cs


[Serializable]
public class MatchmakingPlayer
{
#pragma warning disable 649
#pragma warning restore 649
public string Id => id;
public string Properties

[Serializable]
public class MatchmakingRequest
{
#pragma warning disable 649
#pragma warning restore 649
public List<MatchmakingPlayer> Players
{
get { return players; }

}
}
#pragma warning disable 649
class MatchmakingResult
{
[SerializeField]

internal string error;
}
#pragma warning restore 649
#pragma warning disable 649
#pragma warning restore 649
public string Id => id;

}
[Serializable]
class ConnectionInfo
public class Assignment
#pragma warning disable 649
[SerializeField]
string assignment_error;
[SerializeField]
List<string> roster;
#pragma warning restore 649
public string AssignmentError => assignment_error;
public List<string> Roster
{
get { return roster; }
set { roster = value; }
}
}

10
Assets/Scripts/Networking/Matchmaking/MatchmakingModel.cs.meta


fileFormatVersion: 2
guid: a4730fd26c454a52bb8beea0f83159ef
timeCreated: 1537221979
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

27
CHANGELOG.md


This file contains a summary of the changes that went into each release.
## [0.3.0] - NEXT NEXT NEXT NEXT
## [0.3.1] - 2019-03-11
- Fixed changelog not being properly updated (missing entries under 0.3.0 heading)
- Updated to Unity 2018.3.8f1
- Updated to latest Matchmaker example code
## [0.3.0] - 2019-02-28
- Updated HDRP to version 4.6
- `net.stats 4` now show breakdown of incoming update packets
- Updated to Unity 2018.3f2
- Fix for too agressive framenting of network packets (would fragment before packet was full)
- Improved compression of Schemas (sent out the clients the first time a new entity type is spawned)
- Fixed network tests that were broken at last release
- Added `server.disconnecttimeout` to allow tuning disconnect time
- New type of headless client, "thinclient", to enable stresstesting of server. Start e.g. using `-batchmode -nographics +thinclient +debugmove 1 +connect localhost +thinclient.requested 16` to get 16 client connections.
- Changed `client.updatesendrate` (number of updates from server per second) to `client.updateinterval` (time in simticks between updates from server). Old default was 20 updates/sec and new default is 3; with tickrate of 60 default is thus unchanged.
- The oddly named `owner` to `server` in ServerConnection
- Tweaks to Linux build steps to align with needs of Multiplay (naming etc.)
- Game now looks for `-port` and `-query_port` for port numbers for game resp server query port.
- Lots of optimizations to delta compression and snapshot generation on server
- Redid all the old particles in with cool new Visual Effect Graph
- Fix for crashes in netcode when client had very long stalls
- Converted all of the UI to use Text Mesh Pro
- Server Query Protocol now defaults to the port offset (+10) used by Multiplay
- Fix and from (thanks: carlself) removing hang when joining an 'old' server
- Fix for some elements of menu sometimes becoming unresponsive
- UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP no longer set in project settings. This means ECS systems automatically starts and runs in edit mode (Unless [DisableAutoCreation] attribute is set, which it is for most of our game systems)
- HitCollision no longer uses Unity collision system for queries against moving colliders. For lag compensation server needs to do queries using different historical data and moving Unity physics colliders multiple times per frame is very inefficient. Now queries are handled using custom collision primitives and burst jobs. The structure of the collider and history data is still WIP.
- Unified how ECS components are serialized. Serialized components should now implement either IReplicatedComponent, IPredictedComponent or IInterpolatedComponent and will automatically be serialized appropriately (if attached to entity with replicatedentity component). IMPORTANT: It is currently also required to define a static methods _CreateSerializerFactory_ that returns a serializer factory for the component type. This is something we are working on getting rid of.

4
Packages/manifest.json


"com.unity.analytics": "3.2.2",
"com.unity.cinemachine": "2.1.13",
"com.unity.collab-proxy": "1.2.15",
"com.unity.entities": "0.0.12-preview.18",
"com.unity.mathematics": "0.0.12-preview.18",
"com.unity.entities": "0.0.12-preview.24",
"com.unity.mathematics": "0.0.12-preview.21",
"com.unity.package-manager-ui": "2.0.3",
"com.unity.postprocessing": "2.1.2",
"com.unity.purchasing": "2.0.3",

6
ProjectSettings/EditorSettings.asset


m_SerializationMode: 2
m_LineEndingsForNewScripts: 1
m_DefaultBehaviorMode: 0
m_PrefabRegularEnvironment: {fileID: 102900000, guid: 84277064ea1afde4b88a70e6baca7177, type: 3}
m_PrefabUIEnvironment: {fileID: 0}
m_PrefabRegularEnvironment: {fileID: 102900000, guid: 84277064ea1afde4b88a70e6baca7177,
type: 3}
m_PrefabUIEnvironment: {fileID: 102900000, guid: d9f2588e02566034bbcddac485d9c291,
type: 3}
m_SpritePackerMode: 2
m_SpritePackerPaddingPower: 1
m_EtcTextureCompressorBehavior: 0

6
ProjectSettings/ProjectSettings.asset


xboxOneDisableEsram: 0
xboxOnePresentImmediateThreshold: 0
switchQueueCommandMemory: 0
switchQueueControlMemory: 16384
switchQueueComputeMemory: 262144
switchNVNShaderPoolsGranularity: 33554432
switchNVNDefaultPoolsGranularity: 16777216
switchNVNOtherPoolsGranularity: 16777216
vulkanEnableSetSRGBWrite: 0
m_SupportedAspectRatios:
4:3: 1

switchAllowsRuntimeAddOnContentInstall: 0
switchDataLossConfirmation: 0
switchUserAccountLockEnabled: 0
switchSystemResourceMemory: 16777216
switchSupportedNpadStyles: 3
switchNativeFsCacheSize: 32
switchIsHoldTypeHorizontal: 0

2
ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2018.3.0f2
m_EditorVersion: 2018.3.8f1

12
README.md


Current status at a glance:
```
Unity version: 2018.3 beta 12
Unity version: 2018.3.8f1
Platforms : Windows (client and server) and Linux (server only)
```

Once you have cloned the repository, you should install
the version of Unity that is listed above in the prerequisites section. Make
sure you include windows standalone support in your installation.
sure you include windows standalone support in your installation (and Linux support
if you want to build the Linux headless server).
## Opening the project for the first time

The first time you open the project you need patience! It takes a while
to import all the assets.
> __NOTE__: Due to a bug in Unity 2018.3 beta, you have to take
the following steps right after the initial import:
> 1. Search for `t:model` in the Project search field. Select them all, right click and reimport them.
> 2. Search for `Firstperson_Projection` in the Project search field. Select the 4 shaders, right click and reimport them.
> __NOTE__: Due to a bug in Unity 2018.3, you have to take the following step right after the initial import:
> 1 Search for `Firstperson_Projection` in the Project search field. Select the 4 shaders, right click and reimport them.
> 2 If you have script compile errors related to entities, you need to remove and re-install the entities package.
>
> One day soon we will remove this note and there will be cake.

正在加载...
取消
保存