浏览代码

Merge branch 'develop' into feature/multipie_integration

/main
JS Fauteux 4 年前
当前提交
367549e0
共有 65 个文件被更改,包括 3641 次插入167 次删除
  1. 294
      Assets/BossRoom/Models/CharacterSetController.controller
  2. 55
      Assets/BossRoom/Scripts/Client/ClientCharacterVisualization.cs
  3. 56
      Assets/BossRoom/Scripts/Client/ClientInputSender.cs
  4. 1
      Assets/BossRoom/Scripts/Server/Game/Action/Action.cs
  5. 43
      Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs
  6. 34
      Assets/BossRoom/Scripts/Shared/Game/Action/ActionRequestData.cs
  7. 12
      Assets/BossRoom/Scripts/Shared/NetworkCharacterState.cs
  8. 3
      Packages/manifest.json
  9. 122
      ProjectSettings/GraphicsSettings.asset
  10. 232
      Assets/BossRoom/Prefabs/EnemySpawner.prefab
  11. 7
      Assets/BossRoom/Prefabs/EnemySpawner.prefab.meta
  12. 54
      Assets/BossRoom/Scripts/Client/ClientSpawnerVisualization.cs
  13. 11
      Assets/BossRoom/Scripts/Client/ClientSpawnerVisualization.cs.meta
  14. 52
      Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs
  15. 3
      Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs.meta
  16. 258
      Assets/BossRoom/Scripts/Server/ServerWaveSpawner.cs
  17. 11
      Assets/BossRoom/Scripts/Server/ServerWaveSpawner.cs.meta
  18. 17
      Assets/BossRoom/Scripts/Shared/NetworkSpawnerState.cs
  19. 11
      Assets/BossRoom/Scripts/Shared/NetworkSpawnerState.cs.meta
  20. 39
      README.md
  21. 1
      .metadata/docs/terms-and-conditions.txt
  22. 35
      .metadata/images/icon.jpg
  23. 21
      .metadata/images/preview.png
  24. 16
      .metadata/metadata.yaml
  25. 124
      .yamato/upm-ci.yml
  26. 8
      Packages/com.unity.multiplayer.samples.coop/.npmignore
  27. 11
      Packages/com.unity.multiplayer.samples.coop/CHANGELOG.md
  28. 7
      Packages/com.unity.multiplayer.samples.coop/CHANGELOG.md.meta
  29. 315
      Packages/com.unity.multiplayer.samples.coop/Documentation~/images/example.png
  30. 67
      Packages/com.unity.multiplayer.samples.coop/Documentation~/images/gitlab_ci_secret_variables.png
  31. 555
      Packages/com.unity.multiplayer.samples.coop/Documentation~/images/gitlab_pipeline_download.png
  32. 483
      Packages/com.unity.multiplayer.samples.coop/Documentation~/images/gitlab_pipelines.png
  33. 448
      Packages/com.unity.multiplayer.samples.coop/Documentation~/images/template_in_new_project.png
  34. 137
      Packages/com.unity.multiplayer.samples.coop/Documentation~/index.md
  35. 5
      Packages/com.unity.multiplayer.samples.coop/LICENSE.md
  36. 7
      Packages/com.unity.multiplayer.samples.coop/LICENSE.md.meta
  37. 26
      Packages/com.unity.multiplayer.samples.coop/QAReport.md
  38. 7
      Packages/com.unity.multiplayer.samples.coop/QAReport.md.meta
  39. 39
      Packages/com.unity.multiplayer.samples.coop/README.md
  40. 7
      Packages/com.unity.multiplayer.samples.coop/README.md.meta
  41. 8
      Packages/com.unity.multiplayer.samples.coop/Tests.meta
  42. 8
      Packages/com.unity.multiplayer.samples.coop/Tests/Editor.meta
  43. 22
      Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorExampleTest.cs
  44. 11
      Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorExampleTest.cs.meta
  45. 12
      Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorTests.asmdef
  46. 7
      Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorTests.asmdef.meta
  47. 8
      Packages/com.unity.multiplayer.samples.coop/Tests/Runtime.meta
  48. 24
      Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeExampleTest.cs
  49. 11
      Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeExampleTest.cs.meta
  50. 6
      Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeTests.asmdef
  51. 7
      Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeTests.asmdef.meta
  52. 16
      Packages/com.unity.multiplayer.samples.coop/Third Party Notices.md
  53. 7
      Packages/com.unity.multiplayer.samples.coop/Third Party Notices.md.meta
  54. 20
      Packages/com.unity.multiplayer.samples.coop/package.json
  55. 7
      Packages/com.unity.multiplayer.samples.coop/package.json.meta

294
Assets/BossRoom/Models/CharacterSetController.controller


m_UseAutomaticThresholds: 1
m_NormalizedBlendValues: 0
m_BlendType: 0
--- !u!1102 &-7547485152901491539
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Fall Down
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- {fileID: 5579816715067545514}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1504929105726005784, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-7345246596832709857
AnimatorState:
serializedVersion: 6

m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1101 &-6735739854590397019
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions: []
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: -3516404760485336223}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.75
m_HasExitTime: 1
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &-6270680072761177303
AnimatorStateTransition:
m_ObjectHideFlags: 1

m_Name: WalkRun
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_Transitions:
- {fileID: 8427159825030150999}
- {fileID: 4924297452976420476}
- {fileID: -2323244736882414019}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0

m_UseAutomaticThresholds: 1
m_NormalizedBlendValues: 0
m_BlendType: 0
--- !u!1101 &-2323244736882414019
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: BeginRevive
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 8314685060882719794}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.7413794
m_HasExitTime: 0
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &-2134875305200649429
AnimatorStateTransition:
m_ObjectHideFlags: 1

m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &-1777038757504527503
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions: []
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: -3516404760485336223}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.75
m_HasExitTime: 1
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1102 &-1068572555509609370
AnimatorState:
serializedVersion: 6

m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_Name: Fall Down
- serializedVersion: 1
m_State: {fileID: 8314685060882719794}
m_Position: {x: 520, y: 200, z: 0}
- serializedVersion: 1
m_State: {fileID: 5803934921609956400}
m_Position: {x: 60, y: 340, z: 0}
- serializedVersion: 1
m_State: {fileID: 6995031694560656813}
m_Position: {x: 350, y: 320, z: 0}
- serializedVersion: 1
m_State: {fileID: -7547485152901491539}
m_Position: {x: -30, y: 240, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []

m_DefaultBool: 0
m_Controller: {fileID: 0}
- m_Name: BeginHitReact
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
- m_Name: FallDown
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
- m_Name: BeginRevive
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
- m_Name: Dead
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
- m_Name: StandUp
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0

m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &4924297452976420476
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: Dead
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 6995031694560656813}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.7413794
m_HasExitTime: 0
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &4957634337843930872
AnimatorStateTransition:
m_ObjectHideFlags: 1

m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &5579816715067545514
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: StandUp
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 5803934921609956400}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.87288135
m_HasExitTime: 0
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &5593412509193387231
AnimatorStateTransition:
m_ObjectHideFlags: 1

m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1102 &5803934921609956400
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Stand Up
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- {fileID: -6735739854590397019}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -2919142679728832081, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1109 &6002482201662273439
AnimatorTransition:
m_ObjectHideFlags: 1

m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6995031694560656813
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Dead
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -1504929105726005784, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1107 &8124319401456280373
AnimatorStateMachine:
serializedVersion: 6

m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -1068572555509609370}
--- !u!1102 &8314685060882719794
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Action - Revive
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- {fileID: -1777038757504527503}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -7620468718608648079, guid: 2115c4661f55eff45a5a0f91fc0a12f0, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1101 &8427159825030150999
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: FallDown
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: -7547485152901491539}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.7413794
m_HasExitTime: 0
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &8468659891928091302
AnimatorStateTransition:
m_ObjectHideFlags: 1

55
Assets/BossRoom/Scripts/Client/ClientCharacterVisualization.cs


using System;
using Cinemachine;
using MLAPI;
using UnityEngine;

m_NetState = this.transform.parent.gameObject.GetComponent<NetworkCharacterState>();
m_NetState.DoActionEventClient += this.PerformActionFX;
m_NetState.NetworkLifeState.OnValueChanged += OnLifeStateChanged;
//we want to follow our parent on a spring, which means it can't be directly in the transform hierarchy.
m_Parent = transform.parent;

{
//TODO: [GOMPS-13] break this method out into its own class, so we can drive multi-frame graphical effects.
//FIXME: [GOMPS-13] hook this up to information in the ActionDescription.
m_ClientVisualsAnimator.SetInteger("AttackID", 1);
m_ClientVisualsAnimator.SetTrigger("BeginAttack");
if (data.TargetIds != null && data.TargetIds.Length > 0)
switch (data.ActionTypeEnum)
NetworkedObject targetObject = MLAPI.Spawning.SpawnManager.SpawnedObjects[data.TargetIds[0]];
if (targetObject != null)
{
var targetAnimator = targetObject.GetComponent<BossRoom.Client.ClientCharacter>().ChildVizObject.OurAnimator;
if (targetAnimator != null)
case ActionType.TANK_BASEATTACK:
m_ClientVisualsAnimator.SetInteger("AttackID", 1);
m_ClientVisualsAnimator.SetTrigger("BeginAttack");
if (data.TargetIds != null && data.TargetIds.Length > 0)
targetAnimator.SetTrigger("BeginHitReact");
NetworkedObject targetObject = MLAPI.Spawning.SpawnManager.SpawnedObjects[data.TargetIds[0]];
if (targetObject != null)
{
var targetAnimator = targetObject.GetComponent<BossRoom.Client.ClientCharacter>().ChildVizObject.OurAnimator;
if (targetAnimator != null)
{
targetAnimator.SetTrigger("BeginHitReact");
}
}
}
break;
case ActionType.ARCHER_BASEATTACK:
break;
case ActionType.GENERAL_CHASE:
break;
case ActionType.GENERAL_REVIVE:
m_ClientVisualsAnimator.SetTrigger("BeginRevive");
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void OnLifeStateChanged(LifeState previousValue, LifeState newValue)
{
switch (newValue)
{
case LifeState.ALIVE:
m_ClientVisualsAnimator.SetTrigger("StandUp");
break;
case LifeState.FAINTED:
m_ClientVisualsAnimator.SetTrigger("FallDown");
break;
case LifeState.DEAD:
m_ClientVisualsAnimator.SetTrigger("Dead");
break;
default:
throw new ArgumentOutOfRangeException(nameof(newValue), newValue, null);
}
}

56
Assets/BossRoom/Scripts/Client/ClientInputSender.cs


[RequireComponent(typeof(NetworkCharacterState))]
public class ClientInputSender : NetworkedBehaviour
{
private int m_NpcLayerMask;
/// We detect clicks in Update (because you can miss single discrete clicks in FixedUpdate). But we need to
/// raycast in FixedUpdate, because raycasts done in Update won't work reliably.
/// This nullable vector will be set to a screen coordinate when an attack click was made.
/// We detect clicks in Update (because you can miss single discrete clicks in FixedUpdate). But we need to
/// raycast in FixedUpdate, because raycasts done in Update won't work reliably.
/// This nullable vector will be set to a screen coordinate when an attack click was made.
private System.Nullable<Vector3> m_AttackClickRequest;
private System.Nullable<Vector3> m_ClickRequest;
public override void NetworkStart()
{

}
}
m_NpcLayerMask = LayerMask.GetMask("NPCs");
m_NetworkCharacter = GetComponent<NetworkCharacterState>();
}

if (Input.GetMouseButton(0))
{
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
{
// The MLAPI_INTERNAL channel is a reliable sequenced channel. Inputs should always arrive and be in order that's why this channel is used.

}
if (m_AttackClickRequest != null)
if (m_ClickRequest != null)
if (Physics.Raycast(Camera.main.ScreenPointToRay(m_AttackClickRequest.Value), out hit) && GetTargetObject(ref hit) != 0)
if (Physics.Raycast(Camera.main.ScreenPointToRay(m_ClickRequest.Value), out hit) && GetTargetObject(ref hit) != 0)
//these two actions will queue one after the other, causing us to run over to our target and take a swing.
//if we have clicked on an enemy:
// - two actions will queue one after the other, causing us to run over to our target and take a swing.
//if we have clicked on a fallen friend - we will revive him
chase_data.TargetIds = new ulong[] { GetTargetObject(ref hit) };
chase_data.TargetIds = new ulong[] {GetTargetObject(ref hit)};
var hit_data = new ActionRequestData();
hit_data.ShouldQueue = true; //wait your turn--don't clobber the chase action.
hit_data.ActionTypeEnum = ActionType.TANK_BASEATTACK;
m_NetworkCharacter.ClientSendActionRequest(ref hit_data);
//TODO fixme: there needs to be a better way to check if target is a PC or an NPC
bool isTargetingNPC = hit.transform.gameObject.layer == m_NpcLayerMask;
if (isTargetingNPC)
{
var hit_data = new ActionRequestData();
hit_data.ShouldQueue = true; //wait your turn--don't clobber the chase action.
hit_data.ActionTypeEnum = ActionType.TANK_BASEATTACK;
m_NetworkCharacter.ClientSendActionRequest(ref hit_data);
}
else
{
//proceed to revive the target if it's in FAINTED state
var targetCharacterState = hit.transform.GetComponent<NetworkCharacterState>();
if (targetCharacterState.NetworkLifeState.Value == LifeState.FAINTED)
{
var revive_data = new ActionRequestData();
revive_data.ShouldQueue = true;
revive_data.ActionTypeEnum = ActionType.GENERAL_REVIVE;
revive_data.TargetIds = new [] {GetTargetObject(ref hit)};
m_NetworkCharacter.ClientSendActionRequest(ref revive_data);
}
}
}
else
{

}
m_AttackClickRequest = null;
m_ClickRequest = null;
}
}

if (Input.GetMouseButtonDown(1))
{
m_AttackClickRequest = Input.mousePosition;
m_ClickRequest = Input.mousePosition;
}
}

1
Assets/BossRoom/Scripts/Server/Game/Action/Action.cs


{
case ActionLogic.MELEE: return new MeleeAction(parent, ref data, level);
case ActionLogic.CHASE: return new ChaseAction(parent, ref data, level);
case ActionLogic.REVIVE: return new ReviveAction(parent, ref data, level);
default: throw new System.NotImplementedException();
}
}

43
Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <param name="data">Contains all data necessary to create the action</param>
public void PlayAction(ref ActionRequestData data )
{
this.m_actionPlayer.PlayAction(ref data);
//the character needs to be alive in order to be able to play actions
if (NetState.NetworkLifeState.Value == LifeState.ALIVE)
{
this.m_actionPlayer.PlayAction(ref data);
}
}
/// <summary>

{
//in a more complicated implementation, we might look up all sorts of effects from the inflicter, and compare them
//to our own effects, and modify the damage or healing as appropriate. But in this game, we just take it straight.
//we can't currently heal a dead character back to Alive state.
//that's handled by a separate function.
//TODO: handle death state.
GameObject.Destroy(this.gameObject);
ClearActions();
if (IsNPC)
{
NetState.NetworkLifeState.Value = LifeState.DEAD;
}
else
{
NetState.NetworkLifeState.Value = LifeState.FAINTED;
}
}
/// <summary>
/// Receive a Life State change that brings Fainted characters back to Alive state.
/// </summary>
/// <param name="inflicter">Person reviving the character.</param>
/// <param name="HP">The HP to set to a newly revived character.</param>
public void Revive(ServerCharacter inflicter, int HP)
{
if (NetState.NetworkLifeState.Value == LifeState.FAINTED)
{
NetState.HitPoints.Value = HP;
NetState.NetworkLifeState.Value = LifeState.ALIVE;
}
if (m_aiBrain != null)
if (m_aiBrain != null && NetState.NetworkLifeState.Value == LifeState.ALIVE)
{
m_aiBrain.Update();
}

34
Assets/BossRoom/Scripts/Shared/Game/Action/ActionRequestData.cs


TANK_BASEATTACK,
ARCHER_BASEATTACK,
GENERAL_CHASE,
GENERAL_REVIVE,
}

RANGED,
RANGEDTARGETED,
CHASE,
REVIVE,
//O__O adding a new ActionLogic type? Update Action.MakeAction!
//O__O adding a new ActionLogic branch? Update Action.MakeAction!
/// FIXME: [GOMPS-99] This will be turned into a ScriptableObject.
/// FIXME: [GOMPS-99] This will be turned into a ScriptableObject.
/// ActionLogic that drives this Action. This corresponds to the actual block of code that executes it.
/// ActionLogic that drives this Action. This corresponds to the actual block of code that executes it.
/// by game logic when the action takes effect.
/// by game logic when the action takes effect.
/// How much it consts in Mana to play this Action.
/// How much it consts in Mana to play this Action.
/// How how the Action performer can be from the Target, or how far the action can go (for an untargeted action like a bowshot).
/// How how the Action performer can be from the Target, or how far the action can go (for an untargeted action like a bowshot).
/// Duration in seconds that this Action takes to play.
/// Duration in seconds that this Action takes to play.
/// Time when the Action should do its "main thing" (e.g. when a melee attack should apply damage).
/// Time when the Action should do its "main thing" (e.g. when a melee attack should apply damage).
/// How long the effect this Action leaves behind will last, in seconds.
/// How long the effect this Action leaves behind will last, in seconds.
/// The primary Animation action that gets played when visualizing this Action.
/// The primary Animation action that gets played when visualizing this Action.
/// FIXME [GOMPS-99]: this list will be turned into a collection of Scriptable Objects.
/// FIXME [GOMPS-99]: this list will be turned into a collection of Scriptable Objects.
/// Question: Do we want to show how to do skill levels, as I am doing here?
/// </summary>
public class ActionData

{ ActionType.GENERAL_CHASE, new List<ActionDescription>
{
{new ActionDescription{Logic=ActionLogic.CHASE } }
}
}
}
},
{ ActionType.GENERAL_REVIVE, new List<ActionDescription>
{
{new ActionDescription{Logic=ActionLogic.REVIVE, Amount=10, ExecTime_s=0.3f, Duration_s=0.5f, Anim="Todo" } }
}
}
};
}

12
Assets/BossRoom/Scripts/Shared/NetworkCharacterState.cs


namespace BossRoom
{
public enum LifeState
{
ALIVE,
FAINTED,
DEAD,
}
/// <summary>
/// Contains all NetworkedVars and RPCs of a character. This component is present on both client and server objects.

public NetworkedVarFloat NetworkMovementSpeed { get; } = new NetworkedVarFloat();
public NetworkedVarInt HitPoints;
public NetworkedVarInt Mana;
public NetworkedVarInt Mana;
public NetworkedVar<LifeState> NetworkLifeState { get; } = new NetworkedVar<LifeState>(LifeState.ALIVE);
/// <summary>
/// Gets invoked when inputs are received from the client which own this networked character.
/// </summary>

3
Packages/manifest.json


{
"dependencies": {
"com.unity.learn.iet-framework": "1.2.1",
"com.unity.cinemachine": "2.6.3",
"com.unity.collab-proxy": "1.3.9",
"com.unity.ide.rider": "2.0.7",

"com.unity.multiplayer.multipie": "git@github.com:Unity-Technologies/com.unity.multiplayer.multipie.git",
"com.unity.multiplayer.multipie": "https://github.com/Unity-Technologies/com.unity.multiplayer.multipie.git",
"com.unity.postprocessing": "2.3.0",
"com.unity.test-framework": "1.1.19",
"com.unity.textmeshpro": "3.0.1",

122
ProjectSettings/GraphicsSettings.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!30 &1
GraphicsSettings:
m_ObjectHideFlags: 0
serializedVersion: 13
m_Deferred:
m_Mode: 1
m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
m_DeferredReflections:
m_Mode: 1
m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
m_ScreenSpaceShadows:
m_Mode: 1
m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
m_LegacyDeferred:
m_Mode: 1
m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
m_DepthNormals:
m_Mode: 1
m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
m_MotionVectors:
m_Mode: 1
m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
m_LightHalo:
m_Mode: 1
m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
m_LensFlare:
m_Mode: 1
m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
m_VideoShadersIncludeMode: 2
m_AlwaysIncludedShaders:
- {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_CustomRenderPipeline: {fileID: 0}
m_TransparencySortMode: 0
m_TransparencySortAxis: {x: 0, y: 0, z: 1}
m_DefaultRenderingPath: 1
m_DefaultMobileRenderingPath: 1
m_TierSettings:
- serializedVersion: 5
m_BuildTarget: 1
m_Tier: 0
m_Settings:
standardShaderQuality: 2
renderingPath: 3
hdrMode: 1
realtimeGICPUUsage: 25
useReflectionProbeBoxProjection: 1
useReflectionProbeBlending: 1
useHDR: 1
useDetailNormalMap: 1
useCascadedShadowMaps: 1
prefer32BitShadowMaps: 0
enableLPPV: 1
useDitherMaskForAlphaBlendedShadows: 1
m_Automatic: 0
- serializedVersion: 5
m_BuildTarget: 1
m_Tier: 1
m_Settings:
standardShaderQuality: 2
renderingPath: 3
hdrMode: 1
realtimeGICPUUsage: 25
useReflectionProbeBoxProjection: 1
useReflectionProbeBlending: 1
useHDR: 1
useDetailNormalMap: 1
useCascadedShadowMaps: 1
prefer32BitShadowMaps: 0
enableLPPV: 1
useDitherMaskForAlphaBlendedShadows: 1
m_Automatic: 0
- serializedVersion: 5
m_BuildTarget: 1
m_Tier: 2
m_Settings:
standardShaderQuality: 2
renderingPath: 3
hdrMode: 1
realtimeGICPUUsage: 50
useReflectionProbeBoxProjection: 1
useReflectionProbeBlending: 1
useHDR: 1
useDetailNormalMap: 1
useCascadedShadowMaps: 1
prefer32BitShadowMaps: 0
enableLPPV: 1
useDitherMaskForAlphaBlendedShadows: 1
m_Automatic: 0
m_LightmapStripping: 0
m_FogStripping: 0
m_InstancingStripping: 0
m_LightmapKeepPlain: 1
m_LightmapKeepDirCombined: 1
m_LightmapKeepDynamicPlain: 1
m_LightmapKeepDynamicDirCombined: 1
m_LightmapKeepShadowMask: 1
m_LightmapKeepSubtractive: 1
m_FogKeepLinear: 1
m_FogKeepExp: 1
m_FogKeepExp2: 1
m_AlbedoSwatchInfos: []
m_LightsUseLinearIntensity: 0
m_LightsUseColorTemperature: 0
m_DefaultRenderingLayerMask: 1
m_LogWhenShaderIsCompiled: 0
version https://git-lfs.github.com/spec/v1
<<<<<<< HEAD
oid sha256:a06b62f70a65345f430b10b6241693d1e969fbecffb1c158ac330169470fab52
size 3569
=======
oid sha256:442894020eebc9cfeddc7b95f3e637fdcf033513a507e0fbe231a8e0e4f7d60b
size 2230
>>>>>>> 4459f56 (LFS is terrorising me)

232
Assets/BossRoom/Prefabs/EnemySpawner.prefab


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4132435922419856147
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9136068542165043480}
- component: {fileID: 8205974096611502342}
m_Layer: 0
m_Name: Client_Visuals
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &9136068542165043480
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4132435922419856147}
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_Children:
- {fileID: 3784477753691126980}
m_Father: {fileID: 8727022540156222958}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8205974096611502342
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4132435922419856147}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 65e25a152b731564ebb6096eb5e9f0ed, type: 3}
m_Name:
m_EditorClassIdentifier:
m_NetworkSpawnerState: {fileID: 9132488263322830174}
m_Animator: {fileID: 0}
--- !u!1 &6205854018081152875
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8727022540156222958}
- component: {fileID: 7323075965458333149}
- component: {fileID: -1287160331463954971}
- component: {fileID: 4844841199312666291}
- component: {fileID: 9132488263322830174}
m_Layer: 6
m_Name: EnemySpawner
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8727022540156222958
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6205854018081152875}
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_Children:
- {fileID: 9136068542165043480}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!136 &7323075965458333149
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6205854018081152875}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &-1287160331463954971
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6205854018081152875}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
NetworkedInstanceId: 0
PrefabHash: 15589198230175896383
PrefabHashGenerator: Spawner
AlwaysReplicateAsRoot: 0
DontDestroyWithOwner: 0
--- !u!114 &4844841199312666291
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6205854018081152875}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 49b962917cae99f48a2a598485996b8d, type: 3}
m_Name:
m_EditorClassIdentifier:
m_NetworkSpawnerState: {fileID: 9132488263322830174}
m_NetworkedPrefab: {fileID: -7852138837387268381, guid: f520174fcd7d61441aa46a9923655dcd, type: 3}
m_BlockingMask:
serializedVersion: 2
m_Bits: 1
m_PlayerProximityValidationTimestep: 2
m_NumberOfWaves: 2
m_SpawnsPerWave: 2
m_TimeBetweenSpawns: 0.5
m_TimeBetweenWaves: 5
m_RestartDelay: 10
m_ProximityDistance: 30
m_DormantCooldown: 10
--- !u!114 &9132488263322830174
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6205854018081152875}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4cfeccaf46c46e1458c3f7351d6753b3, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &6882351788430859438
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3784477753691126980}
- component: {fileID: 1033544756360169842}
- component: {fileID: 4871652750507758710}
m_Layer: 0
m_Name: Capsule
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3784477753691126980
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882351788430859438}
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_Children: []
m_Father: {fileID: 9136068542165043480}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &1033544756360169842
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882351788430859438}
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &4871652750507758710
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6882351788430859438}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}

7
Assets/BossRoom/Prefabs/EnemySpawner.prefab.meta


fileFormatVersion: 2
guid: a6647793a8bc7c846abba94be1d257e5
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

54
Assets/BossRoom/Scripts/Client/ClientSpawnerVisualization.cs


using System;
using MLAPI;
using UnityEngine;
namespace BossRoom
{
public class ClientSpawnerVisualization : NetworkedBehaviour
{
[SerializeField]
NetworkSpawnerState m_NetworkSpawnerState;
// TODO: Integrate visuals (GOMPS-123)
[SerializeField]
Animator m_Animator;
public override void NetworkStart()
{
if (!IsClient)
{
enabled = false;
return;
}
m_NetworkSpawnerState.Broken.OnValueChanged += BrokenStateChanged;
m_NetworkSpawnerState.HitPoints.OnValueChanged += HitPointsChanged;
}
void BrokenStateChanged(bool previousValue, bool newValue)
{
if (newValue)
{
if (previousValue == false)
{
// spawner is newly broken
}
}
else
{
if (previousValue)
{
// spawner is newly revived
}
}
}
void HitPointsChanged(int previousValue, int newValue)
{
if (previousValue > newValue && newValue > 0)
{
// received a hit
}
}
}
}

11
Assets/BossRoom/Scripts/Client/ClientSpawnerVisualization.cs.meta


fileFormatVersion: 2
guid: 65e25a152b731564ebb6096eb5e9f0ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

52
Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs


using MLAPI.Spawning;
using UnityEngine;
namespace BossRoom.Server
{
public class ReviveAction : Action
{
private bool m_ExecFired;
private ServerCharacter m_TargetCharacter;
public ReviveAction(ServerCharacter parent, ref ActionRequestData data, int level) : base(parent, ref data, level)
{
}
public override bool Start()
{
if (m_Data.TargetIds == null || m_Data.TargetIds.Length == 0 || !SpawnManager.SpawnedObjects.ContainsKey(m_Data.TargetIds[0]))
{
Debug.Log("Failed to start ReviveAction. The target entity wasn't submitted or doesn't exist anymore");
return false;
}
var targetNeworkedObj = SpawnManager.SpawnedObjects[m_Data.TargetIds[0]];
m_TargetCharacter = targetNeworkedObj.GetComponent<ServerCharacter>();
m_Parent.NetState.ServerBroadcastAction(ref Data);
return true;
}
public override bool Update()
{
if (!m_ExecFired && Time.time - TimeStarted >= Description.ExecTime_s)
{
m_ExecFired = true;
if (m_TargetCharacter.NetState.NetworkLifeState.Value == LifeState.FAINTED)
{
m_TargetCharacter.Revive(m_Parent, (int) m_Data.Amount);
}
else
{
//cancel the action if the target is alive!
Cancel();
return false;
}
}
return true;
}
}
}

3
Assets/BossRoom/Scripts/Server/Game/Action/ReviveAction.cs.meta


fileFormatVersion: 2
guid: 1122d1ad1a0b437c8a0e586ecb64449d
timeCreated: 1610045410

258
Assets/BossRoom/Scripts/Server/ServerWaveSpawner.cs


using System.Collections;
using UnityEngine;
using MLAPI;
namespace BossRoom.Server
{
/// <summary>
/// Component responsible for spawning prefab clones in waves on the server.
/// </summary>
[RequireComponent(typeof(Collider))]
public class ServerWaveSpawner : NetworkedBehaviour
{
[SerializeField]
NetworkSpawnerState m_NetworkSpawnerState;
// amount of hits it takes to break any spawner
const int k_MaxHealth = 3;
// networked object that will be spawned in waves
[SerializeField]
NetworkedObject m_NetworkedPrefab;
// cache reference to our own transform
Transform m_Transform;
// track wave index and reset once all waves are complete
int m_WaveIndex;
// keep reference to our wave spawning coroutine
Coroutine m_WaveSpawning;
// cache array of RaycastHit as it will be reused for player visibility
RaycastHit[] m_Hit;
int m_PlayerLayerMask;
// cache Collider array of OverlapSphere results for player proximity
Collider[] m_Colliders;
[Tooltip("Select which layers will block visibility.")]
[SerializeField]
LayerMask m_BlockingMask;
[Tooltip("Time between player distance & visibility scans, in seconds.")]
[SerializeField]
float m_PlayerProximityValidationTimestep;
[Header("Wave parameters")]
[Tooltip("Total number of waves.")]
[SerializeField]
int m_NumberOfWaves;
[Tooltip("Number of spawns per wave.")]
[SerializeField]
int m_SpawnsPerWave;
[Tooltip("Time between individual spawns, in seconds.")]
[SerializeField]
float m_TimeBetweenSpawns;
[Tooltip("Time between waves, in seconds.")]
[SerializeField]
float m_TimeBetweenWaves;
[Tooltip("Once last wave is spawned, the spawner waits this long to restart wave spawns, in seconds.")]
[SerializeField]
float m_RestartDelay;
[Tooltip("A player must be withing this distance to commence first wave spawn.")]
[SerializeField]
float m_ProximityDistance;
[Tooltip("After being broken, the spawner waits this long to restart wave spawns, in seconds.")]
[SerializeField]
float m_DormantCooldown;
void Awake()
{
m_Transform = transform;
m_PlayerLayerMask = LayerMask.GetMask("PCs");
}
public override void NetworkStart()
{
base.NetworkStart();
if (!IsServer)
{
enabled = false;
return;
}
ReviveSpawner();
m_Hit = new RaycastHit[1];
m_Colliders = new Collider[8];
StartCoroutine(ValidatePlayersProximity(StartWaveSpawning));
}
/// <summary>
/// Coroutine for continually validating proximity to players and invoking an action when any is near.
/// </summary>
/// <param name="validationAction"></param>
/// <returns></returns>
IEnumerator ValidatePlayersProximity(System.Action validationAction)
{
while (true)
{
if (m_NetworkSpawnerState.Broken.Value)
{
yield return new WaitForSeconds(m_DormantCooldown);
ReviveSpawner();
}
if (m_WaveSpawning == null)
{
if (IsAnyPlayerNearbyAndVisible())
{
validationAction();
}
}
else
{
// do nothing, a wave spawning routine is currently underway
}
yield return new WaitForSeconds(m_PlayerProximityValidationTimestep);
}
}
void StartWaveSpawning()
{
StopWaveSpawning();
m_WaveSpawning = StartCoroutine(SpawnWaves());
}
void StopWaveSpawning()
{
if (m_WaveSpawning != null)
{
StopCoroutine(m_WaveSpawning);
}
m_WaveSpawning = null;
}
/// <summary>
/// Coroutine for spawning prefabs clones in waves, waiting a duration before spawning a new wave.
/// Once all waves are completed, it waits a restart time before termination.
/// </summary>
/// <returns></returns>
IEnumerator SpawnWaves()
{
m_WaveIndex = 0;
while (m_WaveIndex < m_NumberOfWaves)
{
yield return SpawnWave();
yield return new WaitForSeconds(m_TimeBetweenWaves);
}
yield return new WaitForSeconds(m_RestartDelay);
m_WaveSpawning = null;
}
/// <summary>
/// Coroutine that spawns a wave of prefab clones, with some time between spawns.
/// </summary>
/// <returns></returns>
IEnumerator SpawnWave()
{
for (int i = 0; i < m_SpawnsPerWave; i++)
{
SpawnPrefab();
yield return new WaitForSeconds(m_TimeBetweenSpawns);
}
m_WaveIndex++;
}
/// <summary>
/// Spawn a NetworkedObject prefab clone.
/// </summary>
void SpawnPrefab()
{
if (m_NetworkedPrefab == null)
{
throw new System.ArgumentNullException("m_NetworkedPrefab");
}
// spawn clone right in front of spawner
var spawnPosition = m_Transform.position + m_Transform.forward;
var clone = Instantiate(m_NetworkedPrefab, spawnPosition, Quaternion.identity);
if (!clone.IsSpawned)
{
clone.Spawn();
}
}
/// <summary>
/// Determines whether any player is within range & visible through RaycastNonAlloc check.
/// </summary>
/// <returns> True if visible and within range, else false. </returns>
bool IsAnyPlayerNearbyAndVisible()
{
var spawnerPosition = m_Transform.position;
var ray = new Ray();
int hits = Physics.OverlapSphereNonAlloc(spawnerPosition,
m_ProximityDistance, m_Colliders, m_PlayerLayerMask);
if (hits == 0)
{
return false;
}
// iterate through players and only return true if a player is in range
// and is not occluded by a blocking collider.
foreach (var playerCollider in m_Colliders)
{
var playerPosition = playerCollider.transform.position;
var direction = playerPosition - spawnerPosition;
ray.origin = spawnerPosition;
ray.direction = direction;
var hit = Physics.RaycastNonAlloc(ray, m_Hit,
Mathf.Min(direction.magnitude, m_ProximityDistance),m_BlockingMask);
if (hit == 0)
{
return true;
}
}
return false;
}
void ReviveSpawner()
{
m_NetworkSpawnerState.HitPoints.Value = k_MaxHealth;
m_NetworkSpawnerState.Broken.Value = false;
}
// TODO: David will create interface hookup for receiving hits on non-NPC/PC objects (GOMPS-ID TBD)
void ReceiveHP(ServerCharacter inflicter, int HP)
{
if (!IsServer)
{
return;
}
m_NetworkSpawnerState.HitPoints.Value += HP;
if (m_NetworkSpawnerState.HitPoints.Value <= 0)
{
m_NetworkSpawnerState.Broken.Value = true;
StopWaveSpawning();
}
}
}
}

11
Assets/BossRoom/Scripts/Server/ServerWaveSpawner.cs.meta


fileFormatVersion: 2
guid: 49b962917cae99f48a2a598485996b8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

17
Assets/BossRoom/Scripts/Shared/NetworkSpawnerState.cs


using MLAPI;
using MLAPI.NetworkedVar;
using UnityEngine;
namespace BossRoom
{
/// <summary>
/// Contains all NetworkedVars of a spawner.
/// This component is present on both client and server objects.
/// </summary>
public class NetworkSpawnerState : NetworkedBehaviour
{
public NetworkedVarInt HitPoints { get; } = new NetworkedVarInt();
public NetworkedVarBool Broken { get; } = new NetworkedVarBool();
}
}

11
Assets/BossRoom/Scripts/Shared/NetworkSpawnerState.cs.meta


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

39
README.md


# TODOs (trimmed down version of tasks listed at: https://github.cds.internal.unity3d.com/unity/com.unity.template-starter-kit)
##### Fill in your project template's package information
Update the following required fields in `Packages/com.unity.template.mytemplate/package.json`:
- `name`: Project template's package name, it should follow this naming convention: `com.unity.template.[your-template-name]`
(Example: `com.unity.template.3d`)
- `displayName`: Package user friendly display name. (Example: `"First person shooter"`). <br>__Note:__ Use a display name that will help users understand what your project template is intended for.
- `version`: Package version `X.Y.Z`, your project **must** adhere to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
- `unity`: Minimum Unity Version your project template is compatible with. (Example: `2018.3`)
- `description`: This is the description for your template which will be displayed to the user to let them know what this template is for. This description shouldn't include anything version-specific and should stay pretty consistent across template versions.
- `dependencies`: Specify the dependencies the template requires. If you add a package to your project, you should also add it here. We try to keep this list as lean as possible to avoid conflicts as much as possible.
##### Update **README.md**
The README.md file should contain all pertinent information for template developers, such as:
* Prerequisites
* External tools or development libraries
* Required installed Software
The Readme file at the root of the project should be the same as the one found in the template package folder.
##### Prepare your documentation
Rename and update **Packages/com.unity.template.mytemplate/Documentation~/your-package-name.md** documentation file.
Use this documentation template to create preliminary, high-level documentation for the _development_ of your template's package. This document is meant to introduce other developers to the features and sample files included in your project template.
Your template's documentation will be made available online and in the editor during publishing to guide our users.
##### Update the changelog
**Packages/com.unity.template.mytemplate/CHANGELOG.md**.
Every new feature or bug fix should have a trace in this file. For more details on the chosen changelog format, see [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
Changelogs will be made available online to inform users about the changes they can expect when downloading a project template. As a consequence, the changelog content should be customer friendly and present clear, meaningful information.
#### Complete the rest of the steps in the link regarding Legal & Testing

1
.metadata/docs/terms-and-conditions.txt


THIS IS THE TERMS AND CONDITIONS PLACEHOLDER

35
.metadata/images/icon.jpg

之前 之后
宽度: 269  |  高度: 195  |  大小: 8.1 KiB

21
.metadata/images/preview.png

之前 之后
宽度: 1101  |  高度: 666  |  大小: 9.8 KiB

16
.metadata/metadata.yaml


packageName: com.unity.template.xxx
name: NEW NAME
description: translationMap
icon: file://images/icon.png
previewImage: file://images/preview.png
category: Core
buildPlatform: Windows
renderPipeline: BuiltIn
termsOfService: file://docs/terms-and-conditions.txt
#extraFields: # (Optional) - A list of extra metadata that can be developer-defined as key/value pairs where value is always a string.
# - name: ageGate
# value: "12+"
translationMap:
description:
en-US: "With this template, blablabla"
zh-CN: "使用此模板,..."

124
.yamato/upm-ci.yml


target_editor:
version: 2019.4
test_editors:
- version: 2019.4
#- version: 2020.1
#- version: 2020.2
#- version: trunk
test_platforms:
- name: win
type: Unity::VM
image: package-ci/win10:stable
flavor: b1.large
- name: mac
type: Unity::VM::osx
image: package-ci/mac:stable
flavor: m1.mac
#- name: ubuntu
# type: Unity::VM
# image: package-ci/ubuntu:stable
# flavor: b1.large
# Use if Linux instance with GPU required
#- name: centos
# type: Unity::VM::GPU
# image: package-ci/centos:stable
# flavor: b1.large
---
prepack:
name: Pre-Pack - Primed Artifacts
agent:
type: Unity::VM
image: package-ci/win10:stable
flavor: b1.large
commands:
- pip install unity-downloader-cli --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
- unity-downloader-cli -u {{target_editor.version}} -c editor -w
- .\.Editor\Unity.exe -batchmode -quit
artifacts:
primed:
paths:
- "Library/Artifacts/**"
- "Library/ArtifactDB"
- "Library/SourceAssetDB"
pack:
name: Pack
agent:
type: Unity::VM
image: package-ci/ubuntu:stable
flavor: b1.large
commands:
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- upm-ci template pack
dependencies:
- .yamato/upm-ci.yml#prepack
artifacts:
packages:
paths:
- "upm-ci~/**/*"
{% for editor in test_editors %}
{% for platform in test_platforms %}
test_{{ platform.name }}_{{ editor.version }}:
name : Test {{ editor.version }} on {{ platform.name }}
agent:
type: {{ platform.type }}
image: {{ platform.image }}
flavor: {{ platform.flavor}}
commands:
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- {% if platform.name == "centos" %}DISPLAY=:0 {% endif %}upm-ci template test -u {{ editor.version }}
artifacts:
logs:
paths:
- "upm-ci~/test-results/**/*"
dependencies:
- .yamato/upm-ci.yml#pack
{% endfor %}
{% endfor %}
test_trigger:
name: Tests Trigger
triggers:
branches:
only:
- "master"
- "dev"
- "/staging-.*/"
pull_requests:
- targets:
only:
- "/.*/"
dependencies:
- .yamato/upm-ci.yml#pack
{% for editor in test_editors %}
{% for platform in test_platforms %}
- .yamato/upm-ci.yml#test_{{platform.name}}_{{editor.version}}
{% endfor %}
{% endfor %}
publish:
name: Publish to Internal Registry
agent:
type: Unity::VM
image: package-ci/win10:stable
flavor: b1.large
commands:
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm
- upm-ci template publish
triggers:
tags:
only:
- /^(r|R)(c|C)-\d+\.\d+\.\d+(-preview(\.\d+)?)?$/
artifacts:
packages:
paths:
- "upm-ci~/packages/**/*"
- "upm-ci~/templates/*.tgz"
dependencies:
- .yamato/upm-ci.yml#pack
{% for editor in test_editors %}
{% for platform in test_platforms %}
- .yamato/upm-ci.yml#test_{{ platform.name }}_{{ editor.version }}
{% endfor %}
{% endfor %}

8
Packages/com.unity.multiplayer.samples.coop/.npmignore


ProjectData~/ProjectSettings/ProjectVersion.txt
ProjectData~/Assets/Scenes.meta
.npmrc
.npmignore
.gitignore
QAReport.md
QAReport.md.meta
.gitlab-ci.yml

11
Packages/com.unity.multiplayer.samples.coop/CHANGELOG.md


# Changelog
All notable changes to this project template will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.1.0] - 2020-10-09
### This is the first release of *Unity Package com.unity.template.mytemplate*.
*Short description of this release*

7
Packages/com.unity.multiplayer.samples.coop/CHANGELOG.md.meta


fileFormatVersion: 2
guid: 6f00b2d43a7ad4286a00be8b13f4a499
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

315
Packages/com.unity.multiplayer.samples.coop/Documentation~/images/example.png

之前 之后
宽度: 748  |  高度: 249  |  大小: 51 KiB

67
Packages/com.unity.multiplayer.samples.coop/Documentation~/images/gitlab_ci_secret_variables.png

之前 之后
宽度: 990  |  高度: 283  |  大小: 16 KiB

555
Packages/com.unity.multiplayer.samples.coop/Documentation~/images/gitlab_pipeline_download.png

之前 之后
宽度: 2518  |  高度: 160  |  大小: 53 KiB

483
Packages/com.unity.multiplayer.samples.coop/Documentation~/images/gitlab_pipelines.png

之前 之后
宽度: 796  |  高度: 1168  |  大小: 101 KiB

448
Packages/com.unity.multiplayer.samples.coop/Documentation~/images/template_in_new_project.png

之前 之后
宽度: 1990  |  高度: 1082  |  大小: 123 KiB

137
Packages/com.unity.multiplayer.samples.coop/Documentation~/index.md


>>>
**_Project Template Documentation_**
Use this template to create preliminary, high-level documentation meant to introduce users to the feature and the sample files included in this project template. When writing your documentation, do the following:
1. Follow instructions in blockquotes.
2. Replace angle brackets with the appropriate text. For example, replace "&lt;template name&gt;" with the official name of the project template.
3. Delete sections that do not apply to your project template. For example, a template containing only sample files does not have a "Using &lt;template name&gt;" section, so this section can be removed.
4. After documentation is completed, make sure you delete all instructions and examples in blockquotes including this preamble and its title:
```
>>>
Delete all of the text between pairs of blockquote markdown.
>>>
```
>>>
# About &lt;template name&gt;
>>>
Name the heading of the first topic after the **displayName** of the project template as it appears in the template's manifest. Check with your Product Manager to ensure that the template is named correctly.
This first topic includes a brief, high-level explanation of the project template and, if applicable, provides links to Unity Manual topics.
>>>
**_Example:_**
>>>
Here is an example for reference only. Do not include this in the final documentation file:
*The First Persion Shooter project template includes examples of First Person Shooter assets, First Person Shooter Instances, animation, GameObjects, game mechanics and scripts that will help you get started quickly with creating your own first person shooter game.*
>>>
<a name="UsingProjectTemplate"></a>
# Using &lt;template name&gt;
>>>
The contents of this section depends on the type of project template.
* At a minimum, this section should include reference documentation that describes the assets, structure, and properties that makes up the project template's content. This reference documentation should include screen grabs (see how to add screens below), a list of assets or settings, an explanation of what each asset or setting does, and the default values of each asset or setting.
* Ideally, this section should also include a workflow: a list of steps that the user can easily follow that demonstrates how to use the project template. This list of steps should include screen grabs (see how to add screens below) to better describe how to use the feature.
For project templates that include sample files, this section may include detailed information on how the user can use these sample files. Workflow diagrams or illustrations could be included if deemed appropriate.
## How to add images
*(This section is for reference. Do not include in the final documentation file)*
If the [Using &lt;template name&gt;](#UsingProjectTemplate) section includes screen grabs or diagrams, a link to the image must be added to this MD file, before or after the paragraph with the instruction or description that references the image. In addition, a caption should be added to the image link that includes the name of the screen or diagram. All images must be PNG files with underscores for spaces. No animated GIFs.
An example is included below:
![A cinematic in the Timeline Editor window.](images/example.png)
Notice that the example screen shot is included in the images folder. All screen grabs and/or diagrams must be added and referenced from the images folder.
For more on the Unity documentation standards for creating and adding screen grabs, see this confluence page: https://confluence.hq.unity3d.com/pages/viewpage.action?pageId=13500715
>>>
# Technical details
## Requirements
>>>
This subtopic includes a bullet list with the compatible versions of Unity. This subtopic may also include additional requirements or recommendations for 3rd party software or hardware. If you need to include references to non-Unity products, make sure you refer to these products correctly and that all references include the proper trademarks (tm or r)
>>>
This version of &lt;template name&gt; is compatible with the following versions of the Unity Editor:
* 2018.3 and later (recommended)
To use this project template, you must have the following 3rd party products:
* &lt;product name and version with trademark or registered trademark.&gt;
* &lt;product name and version with trademark or registered trademark.&gt;
* &lt;product name and version with trademark or registered trademark.&gt;
## Known limitations
>>>
This section lists the known limitations with this version of the project template. If there are no known limitations, or if the limitations are trivial, exclude this section. An example is provided.
>>>
&lt;template name&gt; template version &lt;template version&gt; includes the following known limitations:
* &lt;brief one-line description of first limitation.&gt;
* &lt;brief one-line description of second limitation.&gt;
* &lt;and so on&gt;
>>>
*Example (For reference. Do not include in the final documentation file):*
The First Person Shoot template version 1.0 has the following limitations:*
* The First Person Shooter template does not support sound.
* The First Person Shooter template's Recorder properties are not available in standalone players.
* MP4 encoding is only available on Windows.
>>>
## Project template contents
>>>
This section includes the location of important files you want the user to know about. For example, if this project template containing user interface, models, and materials separated by groups, you may want to provide the folder location of each group.
>>>
The following table indicates the &lt;describe the breakdown you used here&gt;:
|Location|Description|
|---|---|
|`<folder>`|Contains &lt;describe what the folder contains&gt;.|
|`<file>`|Contains &lt;describe what the file represents or implements&gt;.|
>>>
*Example (For reference. Do not include in the final documentation file):*
The following table indicates the root folder of each type of sample in this project template. Each sample's root folder contains its own folders:
|Folder Location|Description|
|---|---|
|`WoodenCrate_Orange`|Root folder containing the assets for the orange crates.|
|`Characters`|Root folder containing the assets and animators for the characters.|
|`Levels`|Root folder containing scenes for the sample game's levels.|
>>>
## Document revision history
>>>
This section includes the revision history of the document. The revision history tracks when a document is created, edited, and updated. If you create or update a document, you must add a new row describing the revision. The Documentation Team also uses this table to track when a document is edited and its editing level. An example is provided:
|Date|Reason|
|---|---|
|Sept 12, 2017|Unedited. Published to production.|
|Sept 10, 2017|Document updated for project template version 1.1.<br>New features: <li>audio support for capturing MP4s.<li>Instructions on saving Recorder prefabs|
|Sept 5, 2017|Limited edit by Documentation Team. Published to production.|
|Aug 25, 2017|Document created. Matches project template version 1.0.|
>>>

5
Packages/com.unity.multiplayer.samples.coop/LICENSE.md


com.unity.multiplayer.samples.coop copyright © 2020 Unity Technologies ApS
Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License).
Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions.

7
Packages/com.unity.multiplayer.samples.coop/LICENSE.md.meta


fileFormatVersion: 2
guid: e1f27ba539e634ffa814b5977253d779
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

26
Packages/com.unity.multiplayer.samples.coop/QAReport.md


# Quality Report
Use this file to outline the test strategy for this project template.
## Version tested: [*package version*]
## QA Owner: [*Add Name*]
## UX Owner: [*Add Name*]
## Test strategy
*Use this section to describe how this feature was tested.*
* A link to the Test Plan (Test Rails, other)
* Results from the project template's editor and runtime test suite.
* Link to automated test results (if any)
* Manual test Results, [here's an example](https://docs.google.com/spreadsheets/d/12A76U5Gf969w10KL4Ik0wC1oFIBDUoRrqIvQgD18TFo/edit#gid=0)
* Scenario test week outcome
* etc.
## Package Status
Use this section to describe:
* UX status/evaluation results
* package stability
* known bugs, issues
* performance metrics,
* etc
In other words, a general feeling on the health of this project template.

7
Packages/com.unity.multiplayer.samples.coop/QAReport.md.meta


fileFormatVersion: 2
guid: 38e03a401f2e04237aa2d319d824266c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

39
Packages/com.unity.multiplayer.samples.coop/README.md


# TODOs (trimmed down version of tasks listed at: https://github.cds.internal.unity3d.com/unity/com.unity.template-starter-kit)
##### Fill in your project template's package information
Update the following required fields in `Packages/com.unity.template.mytemplate/package.json`:
- `name`: Project template's package name, it should follow this naming convention: `com.unity.template.[your-template-name]`
(Example: `com.unity.template.3d`)
- `displayName`: Package user friendly display name. (Example: `"First person shooter"`). <br>__Note:__ Use a display name that will help users understand what your project template is intended for.
- `version`: Package version `X.Y.Z`, your project **must** adhere to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
- `unity`: Minimum Unity Version your project template is compatible with. (Example: `2018.3`)
- `description`: This is the description for your template which will be displayed to the user to let them know what this template is for. This description shouldn't include anything version-specific and should stay pretty consistent across template versions.
- `dependencies`: Specify the dependencies the template requires. If you add a package to your project, you should also add it here. We try to keep this list as lean as possible to avoid conflicts as much as possible.
##### Update **README.md**
The README.md file should contain all pertinent information for template developers, such as:
* Prerequisites
* External tools or development libraries
* Required installed Software
The Readme file at the root of the project should be the same as the one found in the template package folder.
##### Prepare your documentation
Rename and update **Packages/com.unity.template.mytemplate/Documentation~/your-package-name.md** documentation file.
Use this documentation template to create preliminary, high-level documentation for the _development_ of your template's package. This document is meant to introduce other developers to the features and sample files included in your project template.
Your template's documentation will be made available online and in the editor during publishing to guide our users.
##### Update the changelog
**Packages/com.unity.template.mytemplate/CHANGELOG.md**.
Every new feature or bug fix should have a trace in this file. For more details on the chosen changelog format, see [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
Changelogs will be made available online to inform users about the changes they can expect when downloading a project template. As a consequence, the changelog content should be customer friendly and present clear, meaningful information.
#### Complete the rest of the steps in the link regarding Legal & Testing

7
Packages/com.unity.multiplayer.samples.coop/README.md.meta


fileFormatVersion: 2
guid: 0a4025153e1d8462296108e234c57e9a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.samples.coop/Tests.meta


fileFormatVersion: 2
guid: 1977828ca0ab3cf409d003e816121b85
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.samples.coop/Tests/Editor.meta


fileFormatVersion: 2
guid: 638e0ab1bfc544e57b3cbfdeab499e95
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

22
Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorExampleTest.cs


using UnityEngine;
using UnityEditor;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
class EditorExampleTest {
[Test]
public void EditorSampleTestSimplePasses() {
// Use the Assert class to test conditions.
}
// A UnityTest behaves like a coroutine in PlayMode
// and allows you to yield null to skip a frame in EditMode
[UnityTest]
public IEnumerator EditorSampleTestWithEnumeratorPasses() {
// Use the Assert class to test conditions.
// yield to skip a frame
yield return null;
}
}

11
Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorExampleTest.cs.meta


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

12
Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorTests.asmdef


{
"name": "EditorTests",
"references": [
],
"optionalUnityReferences": [
"TestAssemblies"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": []
}

7
Packages/com.unity.multiplayer.samples.coop/Tests/Editor/EditorTests.asmdef.meta


fileFormatVersion: 2
guid: 46638b6bd20197743a152451f938f098
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.samples.coop/Tests/Runtime.meta


fileFormatVersion: 2
guid: 9c55332defd6c4db0938ccca59c5cf10
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

24
Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeExampleTest.cs


using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
namespace Tests
{
public class RuntimeExampleTest
{
[Test]
public void RuntimeExampleTestSimplePasses() {
// Use the Assert class to test conditions.
}
// A UnityTest behaves like a coroutine in PlayMode
// and allows you to yield null to skip a frame in EditMode
[UnityTest]
public IEnumerator RuntimeExampleTestWithEnumeratorPasses() {
// Use the Assert class to test conditions.
// yield to skip a frame
yield return null;
}
}
}

11
Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeExampleTest.cs.meta


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

6
Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeTests.asmdef


{
"name": "RuntimeTests",
"optionalUnityReferences": [
"TestAssemblies"
]
}

7
Packages/com.unity.multiplayer.samples.coop/Tests/Runtime/RuntimeTests.asmdef.meta


fileFormatVersion: 2
guid: 6c3b676f9588f4aa18a2b77306de6976
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

16
Packages/com.unity.multiplayer.samples.coop/Third Party Notices.md


This package contains third-party software components governed by the license(s) indicated below:
---------
Component Name: [provide component name]
License Type: [Provide license type, i.e. "MIT", "Apache 2.0"]
[Provide License Details]
---------
Component Name: [provide component name]
License Type: [Provide license type, i.e. "MIT", "Apache 2.0"]
[Provide License Details]

7
Packages/com.unity.multiplayer.samples.coop/Third Party Notices.md.meta


fileFormatVersion: 2
guid: ef2dc390be95d448f8486cc72b76d010
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

20
Packages/com.unity.multiplayer.samples.coop/package.json


{
"name": "com.unity.multiplayer.samples.coop",
"displayName":"Co-op RPG",
"version": "0.1.0-preview.1",
"type": "template",
"host": "hub",
"unity": "2019.4",
"description": "Replace this string with your own description of the package. This description appears in the Package Manager window when the user selects this package from the list. \n\nFor best results, use this text to summarize: \n\u25AA What the package does \n\u25AA How it can benefit the user \n\nNote: Special formatting characters are supported, including line breaks ('\\n') and bullets ('\\u25AA').",
"dependencies": {
"com.unity.learn.iet-framework": "1.2.1",
"com.unity.multiplayer.mlapi": "0.0.1-preview.1",
"com.unity.test-framework": "1.1.19",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.ui": "1.0.0"
}
}

7
Packages/com.unity.multiplayer.samples.coop/package.json.meta


fileFormatVersion: 2
guid: 56d97389b750f48ea944ff01992cd933
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存