Compare commits
1 Commits
main
...
StartUIFix
Author | SHA1 | Date | |
---|---|---|---|
5ccaeefa5c |
@ -144,10 +144,8 @@ private void CalculateCurrentIncrease(bool moving)
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.M))
|
||||
{
|
||||
if (Input.GetKey(KeyCode.M))
|
||||
_active = !_active;
|
||||
}
|
||||
|
||||
if (!_active)
|
||||
{
|
||||
|
@ -1 +1 @@
|
||||
{"count":1,"self":13.296357599999999,"total":13.6899074,"children":{"InitializeActuators":{"count":2,"self":0.0015034999999999998,"total":0.0015034999999999998,"children":null},"InitializeSensors":{"count":2,"self":0.0010003,"total":0.0010003,"children":null},"AgentSendState":{"count":433,"self":0.0045045,"total":0.2859497,"children":{"CollectObservations":{"count":433,"self":0.2078226,"total":0.2078226,"children":null},"WriteActionMask":{"count":433,"self":0.0009994,"total":0.0009994,"children":null},"RequestDecision":{"count":433,"self":0.0726232,"total":0.0726232,"children":null}}},"DecideAction":{"count":433,"self":0.0019984,"total":0.0019984,"children":null},"AgentAct":{"count":433,"self":0.1020973,"total":0.1020973,"children":null}},"gauges":{},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1704690165","unity_version":"2021.3.14f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2021.3.14f1\\Editor\\Unity.exe -projectpath C:\\Users\\UCUNI\\OneDrive\\Unity\\ML-Agents\\Aimbot-ParallelEnv -useHub -hubIPC -cloudEnvironment production -licensingIpc LicenseClient-bbQe3pofOXaeruEXc-2O8 -hubSessionId fa8ba95e-3ad3-4e58-bbf6-617d74b7cdd4 -accessToken dLDx_lE1nZ6RAtxwNKiPge42G5i8CvH-Sv_7EIEhm2000ef","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.0.1","scene_name":"Play","end_time_seconds":"1704690179"}}
|
||||
{"count":1,"self":6.6978924,"total":6.7403838,"children":{"InitializeActuators":{"count":2,"self":0.002,"total":0.002,"children":null},"InitializeSensors":{"count":2,"self":0.001,"total":0.001,"children":null},"AgentSendState":{"count":96,"self":0.0014992999999999999,"total":0.010006899999999999,"children":{"CollectObservations":{"count":96,"self":0.0050103,"total":0.0050103,"children":null},"WriteActionMask":{"count":96,"self":0.0014992,"total":0.0014992,"children":null},"RequestDecision":{"count":96,"self":0.0019981,"total":0.0019981,"children":null}}},"DecideAction":{"count":96,"self":0.0029998,"total":0.0029998,"children":null},"AgentAct":{"count":96,"self":0.0259858,"total":0.0259858,"children":null}},"gauges":{},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1696776760","unity_version":"2021.3.14f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2021.3.14f1\\Editor\\Unity.exe -projectpath C:\\Users\\UCUNI\\OneDrive\\Unity\\ML-Agents\\Aimbot-ParallelEnv -useHub -hubIPC -cloudEnvironment production -licensingIpc LicenseClient-XEerV7kYNt9lW-ScfLTdo -hubSessionId d21180ac-2b2e-4464-bc29-90cd6d320fc3 -accessToken FUlk05mLlb2dcwVANd09HxpJmsCNwwFXO6GIY0FY5_c00ef","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.0.1","scene_name":"Play","end_time_seconds":"1696776767"}}
|
@ -1 +1 @@
|
||||
{"count":1,"self":103.5483392,"total":107.75784449999999,"children":{"InitializeActuators":{"count":12,"self":0.001004,"total":0.001004,"children":null},"InitializeSensors":{"count":12,"self":0,"total":0,"children":null},"AgentSendState":{"count":1424,"self":0.0280132,"total":2.6909213,"children":{"CollectObservations":{"count":8544,"self":2.640354,"total":2.640354,"children":null},"WriteActionMask":{"count":8544,"self":0.0060129,"total":0.0060129,"children":null},"RequestDecision":{"count":8544,"self":0.0165412,"total":0.0165412,"children":null}}},"DecideAction":{"count":1424,"self":0.0235409,"total":0.0235409,"children":null},"AgentAct":{"count":1424,"self":1.4940384,"total":1.4940384,"children":null}},"gauges":{},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1704689262","unity_version":"2021.3.14f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2021.3.14f1\\Editor\\Unity.exe -projectpath C:\\Users\\UCUNI\\OneDrive\\Unity\\ML-Agents\\Aimbot-ParallelEnv -useHub -hubIPC -cloudEnvironment production -licensingIpc LicenseClient-bbQe3pofOXaeruEXc-2O8 -hubSessionId fa8ba95e-3ad3-4e58-bbf6-617d74b7cdd4 -accessToken dLDx_lE1nZ6RAtxwNKiPge42G5i8CvH-Sv_7EIEhm2000ef","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.0.1","scene_name":"StartScene","end_time_seconds":"1704689369"}}
|
||||
{"count":1,"self":96.1897728,"total":96.582275299999992,"children":{"InitializeActuators":{"count":16,"self":0.00099899999999999989,"total":0.00099899999999999989,"children":null},"InitializeSensors":{"count":16,"self":0.0009993,"total":0.0009993,"children":null},"AgentSendState":{"count":867,"self":0.019012499999999998,"total":0.1588117,"children":{"CollectObservations":{"count":6936,"self":0.1277917,"total":0.1277917,"children":null},"WriteActionMask":{"count":6936,"self":0.0040009,"total":0.0040009,"children":null},"RequestDecision":{"count":6936,"self":0.0080066,"total":0.0080066,"children":null}}},"DecideAction":{"count":867,"self":0.0100142,"total":0.0100142,"children":null},"AgentAct":{"count":867,"self":0.2216761,"total":0.2216761,"children":null}},"gauges":{},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1697442592","unity_version":"2021.3.14f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2021.3.14f1\\Editor\\Unity.exe -projectpath C:\\Users\\UCUNI\\OneDrive\\Unity\\ML-Agents\\Aimbot-ParallelEnv -useHub -hubIPC -cloudEnvironment production -licensingIpc LicenseClient-UCUNI -hubSessionId e4e811a4-b1b9-40c9-bb87-1f58481c4f0b -accessToken CFEM6A4XwpAEfTmhoY1tJ77LSedBMNIqUlXBOmvKzJY00ef","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.0.1","scene_name":"StartScene","end_time_seconds":"1697442688"}}
|
@ -1 +1 @@
|
||||
{"count":1,"self":8.4565711999999991,"total":9.2154213,"children":{"InitializeActuators":{"count":12,"self":0.0009975,"total":0.0009975,"children":null},"InitializeSensors":{"count":12,"self":0.0010008999999999999,"total":0.0010008999999999999,"children":null},"AgentSendState":{"count":241,"self":0.0034963999999999998,"total":0.46725839999999996,"children":{"CollectObservations":{"count":1446,"self":0.460256,"total":0.460256,"children":null},"WriteActionMask":{"count":1446,"self":0.0010002,"total":0.0010002,"children":null},"RequestDecision":{"count":1446,"self":0.0025058,"total":0.0025058,"children":null}}},"DecideAction":{"count":241,"self":0.0050033,"total":0.0050033,"children":null},"AgentAct":{"count":241,"self":0.28359049999999997,"total":0.28359049999999997,"children":null}},"gauges":{},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1704689378","unity_version":"2021.3.14f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2021.3.14f1\\Editor\\Unity.exe -projectpath C:\\Users\\UCUNI\\OneDrive\\Unity\\ML-Agents\\Aimbot-ParallelEnv -useHub -hubIPC -cloudEnvironment production -licensingIpc LicenseClient-bbQe3pofOXaeruEXc-2O8 -hubSessionId fa8ba95e-3ad3-4e58-bbf6-617d74b7cdd4 -accessToken dLDx_lE1nZ6RAtxwNKiPge42G5i8CvH-Sv_7EIEhm2000ef","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.0.1","scene_name":"Train","end_time_seconds":"1704689387"}}
|
||||
{"count":1,"self":28.5910528,"total":28.601550099999997,"children":{"InitializeActuators":{"count":16,"self":0.0010008,"total":0.0010008,"children":null},"InitializeSensors":{"count":16,"self":0.001,"total":0.001,"children":null},"AgentSendState":{"count":1,"self":0.0009989,"total":0.0034985,"children":{"CollectObservations":{"count":8,"self":0.0014998,"total":0.0014998,"children":null},"WriteActionMask":{"count":8,"self":0,"total":0,"children":null},"RequestDecision":{"count":8,"self":0.0009998,"total":0.0009998,"children":null}}},"DecideAction":{"count":1,"self":0.0005,"total":0.0005,"children":null},"AgentAct":{"count":1,"self":0.0044989,"total":0.0044989,"children":null}},"gauges":{},"metadata":{"timer_format_version":"0.1.0","start_time_seconds":"1697452285","unity_version":"2021.3.14f1","command_line_arguments":"C:\\Program Files\\Unity\\Hub\\Editor\\2021.3.14f1\\Editor\\Unity.exe -projectpath C:\\Users\\UCUNI\\OneDrive\\Unity\\ML-Agents\\Aimbot-ParallelEnv -useHub -hubIPC -cloudEnvironment production -licensingIpc LicenseClient-UCUNI -hubSessionId e4e811a4-b1b9-40c9-bb87-1f58481c4f0b -accessToken CFEM6A4XwpAEfTmhoY1tJ77LSedBMNIqUlXBOmvKzJY00ef","communication_protocol_version":"1.5.0","com.unity.ml-agents_version":"2.0.1","scene_name":"Train","end_time_seconds":"1697452314"}}
|
@ -1005,8 +1005,8 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0}
|
||||
m_Material: {fileID: 2100000, guid: f6d46f1e916b3486c90a448a441fac6a, type: 2}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
|
@ -14,7 +14,7 @@ GameObject:
|
||||
- component: {fileID: 5589415219770305708}
|
||||
- component: {fileID: 5589415219770305697}
|
||||
m_Layer: 5
|
||||
m_Name: SingleTargetProbabilityPanel
|
||||
m_Name: SingleTargetLevelProbabilityPanel
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -60,8 +60,8 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 2100000, guid: f6d46f1e916b3486c90a448a441fac6a, type: 2}
|
||||
m_Color: {r: 0.8862745, g: 0.8862745, b: 0.8862745, a: 1}
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
@ -92,8 +92,6 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
singleLevelProbabilityPanel: {fileID: 6536015492050286218, guid: 81d4d787c82b5174caf00af00e9a3cd1, type: 3}
|
||||
targetTitleText: {fileID: 8396012208200061614, guid: 8a180acb9a0ba8b4aacd888419f082ed, type: 3}
|
||||
singleLevelPanelsObjs: []
|
||||
singleLevelPanels: []
|
||||
--- !u!114 &5589415219770305697
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
File diff suppressed because it is too large
Load Diff
@ -488,11 +488,11 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 237721381}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 44d064c42ee56374e94671f4f9f9d650, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 0195eb0e734c7e747bb7f8b669c80fe5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
singleTargetLevelProbabilityPanel: {fileID: 5589415219770305710, guid: 324d8e84c24cdd04ba087763705db1d0, type: 3}
|
||||
startSceneData: {fileID: 0}
|
||||
startSceneData: {fileID: 1072325866}
|
||||
targetLevelProbabilityPanel: []
|
||||
--- !u!1 &294404779
|
||||
GameObject:
|
||||
@ -1763,88 +1763,6 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 852513428}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &968918527
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 968918529}
|
||||
- component: {fileID: 968918528}
|
||||
m_Layer: 0
|
||||
m_Name: CommonParameterContainer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &968918528
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 968918527}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 34839c2831b759d4a8347ab655b00f36, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
lockMouse: 0
|
||||
damage: 50
|
||||
fireRate: 0.5
|
||||
timeLimit: 30
|
||||
lockCameraX: 0
|
||||
lockCameraY: 1
|
||||
oneHotRayTag: 1
|
||||
spawnAgentInAllMap: 1
|
||||
spinRecordMax: 40
|
||||
spinPenaltyThreshold: 10
|
||||
facingInviewEnemyDisCOEF: 0.5
|
||||
group1Tag: Player
|
||||
group2Tag: Enemy
|
||||
hitTargetRewardDefault: 25
|
||||
killTargetEnemyRewardDefault: 25
|
||||
inAreaRewardDefault: 25
|
||||
freeTimeBonusPerSec: 1
|
||||
targetTimeBonusPerSec: 0.5
|
||||
areaTimeBonusPerSec: 0.2
|
||||
distanceReward: 50
|
||||
facingTargetReward: 10
|
||||
goWinRewardDefault: 999
|
||||
attackWinRewardDefault: 999
|
||||
defenceWinRewardDefault: 999
|
||||
freeWinRewardDefault: 999
|
||||
nonReward: -1
|
||||
loseReward: -999
|
||||
shootReward: -0.5
|
||||
hitNonTargetReward: -5
|
||||
killNonTargetReward: -5
|
||||
shootWithoutReadyReward: -1.15
|
||||
killBonusReward: 0
|
||||
facingReward: 5
|
||||
shootTargetAreaReward: 10
|
||||
movePenalty: 0.1
|
||||
spinPenalty: 0.08
|
||||
mousePenalty: 0.06
|
||||
scenePrefabSet: {fileID: 11400000, guid: 6ebbd27eb466c4a41bd2584c1b9c2e1f, type: 2}
|
||||
--- !u!4 &968918529
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 968918527}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 5
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1064099385
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -2126,6 +2044,58 @@ RectTransform:
|
||||
m_AnchoredPosition: {x: -100, y: -7}
|
||||
m_SizeDelta: {x: 160, y: 30}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &1072325866
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1072325868}
|
||||
- component: {fileID: 1072325867}
|
||||
m_Layer: 0
|
||||
m_Name: StartSceneDataTransfer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1072325867
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1072325866}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 52ba7faaa6129cf418f26c5933d4ea0e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
gameMode: 0
|
||||
scenePrefabSet: {fileID: 11400000, guid: 6ebbd27eb466c4a41bd2584c1b9c2e1f, type: 2}
|
||||
attackProb: 0
|
||||
attackLevelProbs: []
|
||||
gotoProb: 0
|
||||
gotoLevelProbs: []
|
||||
defenceProb: 0
|
||||
defenceLevelProbs: []
|
||||
--- !u!4 &1072325868
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1072325866}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 4
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1144208395
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -2278,7 +2248,7 @@ Transform:
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 4
|
||||
m_RootOrder: 5
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1273196676
|
||||
GameObject:
|
||||
@ -2603,6 +2573,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
waitTimeLimit: 45
|
||||
sceneLoaderObj: {fileID: 1206568295}
|
||||
startSceneDataObj: {fileID: 1072325866}
|
||||
targetLevelProbabilityPanelOBJ: {fileID: 237721381}
|
||||
messageTextObj: {fileID: 294404781}
|
||||
waitTimeTextObj: {fileID: 431112176}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public static class EventTriggerExtensions
|
||||
{
|
||||
public static void AddEventTrigger(this EventTrigger trigger, EventTriggerType type, UnityEngine.Events.UnityAction<BaseEventData> action)
|
||||
{
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = type;
|
||||
entry.callback.AddListener(action);
|
||||
trigger.triggers.Add(entry);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fd51a74b20da1040b8f0d4db7d9ef70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,11 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class Vector3PositionExtensions
|
||||
{
|
||||
public static Vector3 FixCanvas(this Vector3 position,Vector3 originalVanvas,Vector3 nowVanvas)
|
||||
{
|
||||
return position + nowVanvas - originalVanvas;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60aebf9c97041a74eaa7c10ce97e7ba0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class TargetTypeExtensions
|
||||
public static class targetTypeExtensions
|
||||
{
|
||||
public static int ToIndex(this Targets targetType)
|
||||
{
|
||||
|
@ -5,7 +5,14 @@
|
||||
|
||||
public class AgentController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] public Camera fpsCam;
|
||||
public GameObject parameterContainerObj;
|
||||
public GameObject environmentObj;
|
||||
public GameObject enemyContainerObj;
|
||||
public GameObject sceneBlockContainerObj;
|
||||
public GameObject environmentUIControlObj;
|
||||
public GameObject targetControllerObj;
|
||||
public GameObject HUDObj;
|
||||
public Camera fpsCam;
|
||||
|
||||
[Header("GetAxis() Simulate")]
|
||||
public float moveSpeed = 9.0f;
|
||||
@ -18,36 +25,48 @@ public class AgentController : MonoBehaviour
|
||||
public float mouseYSensitivity = 200;
|
||||
public float yRotation = 0.1f;//定义一个浮点类型的量,记录‘围绕’X轴旋转的角度
|
||||
|
||||
private List<float> spinRecord = new List<float>();
|
||||
private bool lockMouse;
|
||||
private float damage;
|
||||
private float fireRate;
|
||||
private bool lockCameraX;
|
||||
private bool lockCameraY;
|
||||
|
||||
// environment
|
||||
public float lastShootTime = 0.0f;
|
||||
private float lastShootTime = 0.0f;
|
||||
|
||||
public int enemyKillCount = 0;
|
||||
public Vector3 killEnemyPosition;
|
||||
private int enemyKillCount = 0;
|
||||
private Vector3 killEnemyPosition;
|
||||
public bool defaultTPCamera = true;
|
||||
|
||||
[System.NonSerialized] public bool gunReadyToggle = true;
|
||||
public string myTag = "";
|
||||
private string myTag = "";
|
||||
private float lastEnemyFacingDistance = 0f; // record last enemy facing minimum distance
|
||||
private float lastTargetFacingDistance = 0f; // record last target facing minimum distance
|
||||
|
||||
// scripts
|
||||
private RaySensors raySensors;
|
||||
|
||||
private CharacterController playerController;
|
||||
private CommonParameterContainer commonPramCon;
|
||||
private ParameterContainer paramContainer;
|
||||
private SceneBlockContainer blockContainer;
|
||||
private TargetController targetCon;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// initialize scripts
|
||||
commonPramCon = CommonParameterContainer.Instance;
|
||||
playerController = transform.GetComponent<CharacterController>();
|
||||
paramContainer = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
blockContainer = sceneBlockContainerObj.GetComponent<SceneBlockContainer>();
|
||||
targetCon = targetControllerObj.GetComponent<TargetController>();
|
||||
raySensors = GetComponent<RaySensors>();
|
||||
playerController = this.transform.GetComponent<CharacterController>();
|
||||
|
||||
// initialize Environment parameters
|
||||
lockMouse = commonPramCon.lockMouse;
|
||||
fireRate = commonPramCon.fireRate;
|
||||
lockCameraX = commonPramCon.lockCameraX;
|
||||
lockCameraY = commonPramCon.lockCameraY;
|
||||
lockMouse = paramContainer.lockMouse;
|
||||
damage = paramContainer.damage;
|
||||
fireRate = paramContainer.fireRate;
|
||||
lockCameraX = paramContainer.lockCameraX;
|
||||
lockCameraY = paramContainer.lockCameraY;
|
||||
|
||||
// initialize remainTime
|
||||
// this agent's tag
|
||||
@ -172,7 +191,234 @@ public void CameraControl(float Mouse_X, float Mouse_Y)
|
||||
|
||||
#endregion Camera Control
|
||||
|
||||
// Got Kill point
|
||||
#region Reward Functions
|
||||
|
||||
// ballistic 射击弹道处理,并返回获得reward
|
||||
private float Ballistic(int shootState)
|
||||
{
|
||||
Vector3 point = new Vector3(fpsCam.pixelWidth / 2, fpsCam.pixelHeight / 2, 0);//发射位置
|
||||
Ray ray = fpsCam.ScreenPointToRay(point);
|
||||
RaycastHit hit;
|
||||
// Debug.DrawRay(centerRay.origin, centerRay.direction * 100, Color.blue);
|
||||
//按下鼠标左键
|
||||
if (shootState != 0 && gunReadyToggle == true)
|
||||
{
|
||||
lastShootTime = Time.time;
|
||||
if (Physics.Raycast(ray, out hit, 100))
|
||||
{
|
||||
if (hit.collider.tag != myTag && hit.collider.tag != "Wall" && hit.collider.tag != "Untagged")
|
||||
{
|
||||
// kill enemy
|
||||
GameObject gotHitObj = hit.transform.gameObject;//获取受到Ray撞击的对象
|
||||
gotHitObj.GetComponent<States>().ReactToHit(damage, gameObject);
|
||||
shootState = 0;
|
||||
return targetCon.HitEnemyReward(gotHitObj.transform.position);
|
||||
}
|
||||
}
|
||||
if (targetCon.targetTypeInt == (int)Targets.Attack)
|
||||
{
|
||||
// while if attack mode
|
||||
float targetDis = Vector3.Distance(blockContainer.nowBlock.transform.position, transform.position);
|
||||
if (targetDis <= raySensors.viewDistance)
|
||||
{
|
||||
// Debug.DrawRay(new Vector3(0,0,0), viewPoint, Color.red);
|
||||
if (Vector3.Distance(ray.origin + (ray.direction * targetDis), blockContainer.nowBlock.transform.position) <= blockContainer.nowBlock.firebasesAreaDiameter / 2)
|
||||
{
|
||||
// im shooting at target but didn't hit enemy
|
||||
// Debug.DrawRay(centerRay.origin, viewPoint-centerRay.origin, Color.blue);
|
||||
return paramContainer.shootTargetAreaReward;
|
||||
}
|
||||
}
|
||||
}
|
||||
shootState = 0;
|
||||
return paramContainer.shootReward;
|
||||
}
|
||||
else if (shootState != 0 && gunReadyToggle == false)
|
||||
{
|
||||
// shoot without ready
|
||||
shootState = 0;
|
||||
return paramContainer.shootWithoutReadyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do not shoot
|
||||
shootState = 0;
|
||||
return paramContainer.nonReward;
|
||||
}
|
||||
}
|
||||
|
||||
private float FacingReward()
|
||||
{
|
||||
float nowReward = 0;
|
||||
bool isFacingtoEnemy = false;
|
||||
float enemyFacingDistance = 0f;
|
||||
|
||||
Vector3 screenCenter = new Vector3(fpsCam.pixelWidth / 2, fpsCam.pixelHeight / 2, 0);
|
||||
Vector3 screenLeft = new Vector3(0, fpsCam.pixelHeight / 2, 0);
|
||||
|
||||
Ray centerRay = fpsCam.ScreenPointToRay(screenCenter);
|
||||
Ray leftRay = fpsCam.ScreenPointToRay(screenLeft);
|
||||
|
||||
// target fireBaseArea Position, turen y to camera's y
|
||||
Vector3 fireBaseArea = blockContainer.nowBlock.fireBasesAreaObj.transform.position;
|
||||
fireBaseArea.y = fpsCam.transform.position.y;
|
||||
|
||||
// my position, turn y to camera's y
|
||||
// Debug.DrawRay(fpsCam.transform.position, centerRay.direction * 100, Color.blue);
|
||||
Vector3 myposition = transform.position;
|
||||
myposition.y = fpsCam.transform.position.y;
|
||||
|
||||
// Target to Agent distance
|
||||
//Debug.DrawLine(fireBaseArea, myposition, Color.red);
|
||||
float targetDis = Vector3.Distance(fireBaseArea, myposition);
|
||||
|
||||
// point in centerRay and leftRay which distance is targetDis from camera center
|
||||
Vector3 pointInCenterRay = fpsCam.transform.position + (centerRay.direction * targetDis);
|
||||
Vector3 pointInLeftRay = fpsCam.transform.position + (leftRay.direction * targetDis);
|
||||
|
||||
// center of screen to target's distance
|
||||
// Debug.DrawLine(pointInCenterRay, fireBaseArea,Color.green);
|
||||
float camCenterToTarget = Vector3.Distance(pointInCenterRay, fireBaseArea);
|
||||
|
||||
// left of screen to target's distance
|
||||
// Debug.DrawLine(pointInLeftRay, pointInCenterRay, Color.yellow);
|
||||
float camCenterToViewEdge = Vector3.Distance(pointInLeftRay, pointInCenterRay);
|
||||
|
||||
switch (targetCon.targetTypeInt)
|
||||
{
|
||||
case (int)Targets.Free:
|
||||
//free mode
|
||||
RaycastHit hit;
|
||||
if (Physics.Raycast(centerRay, out hit, 100))
|
||||
{
|
||||
// facing to an enemy
|
||||
if (hit.collider.tag != myTag && hit.collider.tag != "Wall")
|
||||
{
|
||||
nowReward = paramContainer.facingReward;
|
||||
isFacingtoEnemy = true;
|
||||
}
|
||||
}
|
||||
if (raySensors.inViewEnemies.Count > 0 && !isFacingtoEnemy)
|
||||
{
|
||||
// have enemy in view
|
||||
List<float> projectionDis = new List<float>();
|
||||
foreach (GameObject theEnemy in raySensors.inViewEnemies)
|
||||
{
|
||||
// for each enemy in view
|
||||
Vector3 projection = Vector3.Project(theEnemy.transform.position - transform.position, (centerRay.direction * 10));
|
||||
Vector3 verticalToRay = transform.position + projection - theEnemy.transform.position;
|
||||
projectionDis.Add(verticalToRay.magnitude);
|
||||
// Debug.Log("enemy!" + verticalToRay.magnitude);
|
||||
// Debug.DrawRay(transform.position, (centerRay.direction * 100), Color.cyan);
|
||||
// Debug.DrawRay(transform.position, theEnemy.transform.position - transform.position, Color.yellow);
|
||||
// Debug.DrawRay(transform.position, projection, Color.blue);
|
||||
// Debug.DrawRay(theEnemy.transform.position, verticalToRay, Color.magenta);
|
||||
}
|
||||
enemyFacingDistance = projectionDis.Min();
|
||||
if (enemyFacingDistance <= lastEnemyFacingDistance)
|
||||
{
|
||||
// closing to enemy
|
||||
nowReward = 1 / MathF.Sqrt(paramContainer.facingInviewEnemyDisCOEF * enemyFacingDistance + 0.00001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
nowReward = 0;
|
||||
}
|
||||
// enemy in view Reward
|
||||
lastEnemyFacingDistance = enemyFacingDistance;
|
||||
if (nowReward >= paramContainer.facingReward) nowReward = paramContainer.facingReward; // limit
|
||||
if (nowReward <= -paramContainer.facingReward) nowReward = -paramContainer.facingReward; // limit
|
||||
// Debug.Log("ninimum = " + nowReward);
|
||||
}
|
||||
break;
|
||||
case (int)Targets.Attack:
|
||||
// attack mode
|
||||
if (targetDis <= raySensors.viewDistance)
|
||||
{
|
||||
// Debug.DrawRay(new Vector3(0,0,0), viewPoint, Color.red);
|
||||
// while center of screen between target's distance is lower than firebasesAreaDiameter
|
||||
// while facing to target
|
||||
if (camCenterToTarget <= blockContainer.nowBlock.firebasesAreaDiameter / 2)
|
||||
{
|
||||
// Debug.DrawRay(centerRay.origin, viewPoint-centerRay.origin, Color.blue);
|
||||
nowReward = paramContainer.facingReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// while not facing to target
|
||||
nowReward = (lastTargetFacingDistance - camCenterToTarget) * paramContainer.facingTargetReward;
|
||||
}
|
||||
}
|
||||
// update lastTargetFacingDistance
|
||||
lastTargetFacingDistance = camCenterToTarget;
|
||||
break;
|
||||
case (int)Targets.Go:
|
||||
// goto mode
|
||||
if (camCenterToTarget <= camCenterToViewEdge)
|
||||
{
|
||||
// fireArea is in view
|
||||
nowReward = paramContainer.facingReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
nowReward = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug.LogError("Wrong target type");
|
||||
break;
|
||||
}
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
public float RewardCalculate(float sceneReward, float mouseX, float movement, int shootState)
|
||||
{
|
||||
float epreward = 0f;
|
||||
// 击杀reward判断
|
||||
if (enemyKillCount > 0)
|
||||
{
|
||||
for (int i = 0; i < enemyKillCount; i++)
|
||||
{
|
||||
// get
|
||||
epreward += targetCon.KillReward(killEnemyPosition);
|
||||
}
|
||||
enemyKillCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
enemyKillCount = 0;
|
||||
}
|
||||
// 射击动作reward判断
|
||||
epreward += Ballistic(shootState) + sceneReward;
|
||||
// facing reward
|
||||
epreward += FacingReward();
|
||||
// Penalty
|
||||
// spin penalty
|
||||
spinRecord.Add(mouseX);
|
||||
if (spinRecord.Count >= paramContainer.spinRecordMax)
|
||||
{
|
||||
spinRecord.RemoveAt(0);
|
||||
}
|
||||
float spinPenaltyReward = Math.Abs(spinRecord.ToArray().Sum() * paramContainer.spinPenalty);
|
||||
if (spinPenaltyReward >= paramContainer.spinPenaltyThreshold)
|
||||
{
|
||||
epreward -= spinPenaltyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
epreward -= Math.Abs(mouseX) * paramContainer.mousePenalty;
|
||||
}
|
||||
// move penalty
|
||||
if (movement != 0)
|
||||
{
|
||||
epreward -= paramContainer.movePenalty;
|
||||
}
|
||||
return epreward;
|
||||
}
|
||||
|
||||
#endregion Reward Functions
|
||||
|
||||
// GotKill 获得击杀时用于被呼出
|
||||
public void KillRecord(Vector3 killEnemyPosition)
|
||||
{
|
||||
enemyKillCount += 1;
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
public class EnemyContainer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] public GameObject enemyPrefab;
|
||||
[SerializeField] private GameObject environmentObj;
|
||||
[SerializeField] private GameObject targetControllerObj;
|
||||
public GameObject enemyPrefab;
|
||||
public GameObject environmentObj;
|
||||
public GameObject targetControllerObj;
|
||||
|
||||
private TargetController targetCon;
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class CommonParameterContainer : Singleton<CommonParameterContainer>
|
||||
{
|
||||
[Header("Env")]
|
||||
public bool lockMouse = false;
|
||||
public float damage = 50; // damage to enemy
|
||||
public float fireRate = 0.5f;
|
||||
public int timeLimit = 30;
|
||||
public bool lockCameraX = false;
|
||||
public bool lockCameraY = true;
|
||||
public bool oneHotRayTag = true;
|
||||
public bool spawnAgentInAllMap = true;
|
||||
public int spinRecordMax = 40;
|
||||
public float spinPenaltyThreshold = 10;
|
||||
public float facingInviewEnemyDisCOEF = 0.5f;
|
||||
public string group1Tag = "Player";
|
||||
public string group2Tag = "Enemy";
|
||||
|
||||
[Header("Dynamic Defaut Rewards")]
|
||||
//[Tooltip("Hit Enemy reward")]
|
||||
//public float hitRewardDefault = 60.0f;
|
||||
[Tooltip("Free mode Hit Enemy reward")]
|
||||
public float hitTargetRewardDefault = 25f;
|
||||
//[Tooltip("Enemy down reward")]
|
||||
//public float killRewardDefault = 60.0f;
|
||||
[Tooltip("Enemy down in area Reward")]
|
||||
public float killTargetEnemyRewardDefault = 25f;
|
||||
[Tooltip("stay in firebasesArea reward")]
|
||||
public float inAreaRewardDefault = 25.0f;
|
||||
[Tooltip("free left time bonus reward. ALLR + leftTime * r")]
|
||||
public float freeTimeBonusPerSec = 1.0f;
|
||||
[Tooltip("target left time bonus reward. ALLR + leftTime * r")]
|
||||
public float targetTimeBonusPerSec = 0.5f;
|
||||
[Tooltip("in area left time bonus reward. ALLR + leftTime * r")]
|
||||
public float areaTimeBonusPerSec = 0.2f;
|
||||
[Tooltip("distance reward reward = r*(1-(nowDis/startDis))")]
|
||||
public float distanceReward = 50.0f;
|
||||
[Tooltip("facing to Target distance reward reward = r*(1-(nowDis/startDis))")]
|
||||
public float facingTargetReward = 10.0f;
|
||||
|
||||
[Space(10)]
|
||||
[Tooltip("Goto Win reward")]
|
||||
public float goWinRewardDefault = 999f;
|
||||
[Tooltip("Attack Win reward")]
|
||||
public float attackWinRewardDefault = 999f;
|
||||
[Tooltip("Defence Win reward")]
|
||||
public float defenceWinRewardDefault = 999f;
|
||||
[Tooltip("free Win reward")]
|
||||
public float freeWinRewardDefault = 999f;
|
||||
|
||||
[Header("Static Rewards")]
|
||||
[Tooltip("Nothing happened reward")]
|
||||
public float nonReward = -1f;
|
||||
[Tooltip("Episode Lose reward")]
|
||||
public float loseReward = -999f;
|
||||
[Tooltip("Agent Do shoot action reward")]
|
||||
public float shootReward = -0.5f;
|
||||
[Tooltip("Hit Not target Enemy reward")]
|
||||
public float hitNonTargetReward = -5f;
|
||||
[Tooltip("Not Target Enemy down reward")]
|
||||
public float killNonTargetReward = -5f;
|
||||
[Tooltip("Agent Do shoot action but gun is not read")]
|
||||
public float shootWithoutReadyReward = -1.15f;
|
||||
[Tooltip("Kill bonus reward stack to nothing happend reward")]
|
||||
public float killBonusReward = 0.0f;
|
||||
[Tooltip("Facing to enemy's reward")]
|
||||
public float facingReward = 5f;
|
||||
[Tooltip("Shoot at target area but didn't hit enemy")]
|
||||
public float shootTargetAreaReward = 10f;
|
||||
|
||||
[Header("Penalty Rewards")]
|
||||
[Tooltip("move Penalty Reward")]
|
||||
public float movePenalty = 0.1f;
|
||||
[Tooltip("spiiiiiiin Panalty Reward")]
|
||||
public float spinPenalty = 0.08f;
|
||||
[Tooltip("while move mouse a little bit's penalty")]
|
||||
public float mousePenalty = 0.06f;
|
||||
|
||||
public SceneBlocksSet scenePrefabSet;
|
||||
|
||||
[NonSerialized] public int gameMode; // 0 = trainning mode, 1 = play mode
|
||||
[NonSerialized] public float attackProb = 0f;
|
||||
[NonSerialized] public float gotoProb = 0f;
|
||||
[NonSerialized] public float defenceProb = 0f;
|
||||
|
||||
public Dictionary<Targets, List<float>> levelProbs = new Dictionary<Targets, List<float>>();
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
scenePrefabSet.InitializeSceneBlocksSet();
|
||||
InitializeLevelProbs();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Instance.KeepThroughSceneChange();
|
||||
}
|
||||
|
||||
// Initialize Common Parameters
|
||||
private void InitializeLevelProbs()
|
||||
{
|
||||
for(int i = 0; i< scenePrefabSet.targetLevels.Length; i++)
|
||||
{
|
||||
Targets nowTarget = scenePrefabSet.targets[i];
|
||||
levelProbs[nowTarget] = new List<float>();
|
||||
float levelNum = scenePrefabSet.GetLevelNumber(nowTarget);
|
||||
float averageProbability = 1f / levelNum;
|
||||
float lastLevelProbability = 1f - averageProbability * (levelNum - 1);
|
||||
for (int j = 0; j < levelNum-1; j++)
|
||||
{
|
||||
levelProbs[nowTarget].Add(averageProbability);
|
||||
}
|
||||
levelProbs[nowTarget].Add(lastLevelProbability);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34839c2831b759d4a8347ab655b00f36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -7,18 +7,19 @@
|
||||
|
||||
public class MLAgentsCustomController : Agent
|
||||
{
|
||||
[SerializeField] private GameObject paramContainerObj;
|
||||
[SerializeField] private GameObject targetControllerObj;
|
||||
[SerializeField] private GameObject environmentUIObj;
|
||||
[SerializeField] private GameObject sideChannelObj;
|
||||
[SerializeField] private GameObject worldUIControllerObj;
|
||||
[SerializeField] private GameObject hudObj;
|
||||
public GameObject paramContainerObj;
|
||||
public GameObject targetControllerObj;
|
||||
public GameObject environmentUIObj;
|
||||
public GameObject sideChannelObj;
|
||||
public GameObject hudUIObj;
|
||||
|
||||
[Header("Env")]
|
||||
public bool oneHotRayTag = true;
|
||||
|
||||
// script
|
||||
private AgentController agentController;
|
||||
|
||||
private ParameterContainer paramContainer;
|
||||
private CommonParameterContainer commonParamCon;
|
||||
private TargetController targetController;
|
||||
private EnvironmentUIControl envUIController;
|
||||
private HUDController hudController;
|
||||
@ -26,41 +27,42 @@ public class MLAgentsCustomController : Agent
|
||||
private RaySensors raySensors;
|
||||
private MessageBoxController messageBoxController;
|
||||
private AimBotSideChannelController sideChannelController;
|
||||
private WorldUIController worldUICon;
|
||||
private RewardFunction rewardFunction;
|
||||
|
||||
// observation
|
||||
private float[] myObserve = new float[5];
|
||||
private float[] myObserve = new float[4];
|
||||
|
||||
private float[] rayTagResult;
|
||||
private float[] rayTagResultOnehot;
|
||||
private float[] rayDisResult;
|
||||
private float[] targetStates;
|
||||
private float remainTime;
|
||||
private float inFireBaseState;
|
||||
private float inAreaState;
|
||||
|
||||
private int endTypeInt;
|
||||
private int finishedState;
|
||||
private int step = 0;
|
||||
private int EP = 0;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
agentController = transform.GetComponent<AgentController>();
|
||||
raySensors = transform.GetComponent<RaySensors>();
|
||||
paramContainer = paramContainerObj.GetComponent<ParameterContainer>();
|
||||
commonParamCon = CommonParameterContainer.Instance;
|
||||
targetController = targetControllerObj.GetComponent<TargetController>();
|
||||
envUIController = environmentUIObj.GetComponent<EnvironmentUIControl>();
|
||||
hudController = hudObj.GetComponent<HUDController>();
|
||||
targetUIController = hudObj.GetComponent<TargetUIController>();
|
||||
messageBoxController = hudObj.GetComponent<MessageBoxController>();
|
||||
hudController = hudUIObj.GetComponent<HUDController>();
|
||||
targetUIController = hudUIObj.GetComponent<TargetUIController>();
|
||||
messageBoxController = hudUIObj.GetComponent<MessageBoxController>();
|
||||
sideChannelController = sideChannelObj.GetComponent<AimBotSideChannelController>();
|
||||
rewardFunction = gameObject.GetComponent<RewardFunction>();
|
||||
worldUICon = worldUIControllerObj.GetComponent<WorldUIController>();
|
||||
}
|
||||
|
||||
#region On episode begin function
|
||||
|
||||
public override void OnEpisodeBegin()
|
||||
{
|
||||
step = 0;
|
||||
agentController.UpdateLockMouse();
|
||||
paramContainer.ResetTimeBonusReward();
|
||||
if (commonParamCon.gameMode == 0)
|
||||
if (paramContainer.gameMode == 0)
|
||||
{
|
||||
// train mode
|
||||
Debug.Log("MLAgentCustomController.OnEpisodeBegin: train mode start");
|
||||
@ -70,7 +72,7 @@ public override void OnEpisodeBegin()
|
||||
{
|
||||
Debug.Log("MLAgentCustomController.OnEpisodeBegin: play mode start");
|
||||
// play mode
|
||||
targetController.PlayModeInitialize();
|
||||
targetController.PlayInitialize();
|
||||
// reset target UI
|
||||
targetUIController.ClearGamePressed();
|
||||
}
|
||||
@ -83,6 +85,10 @@ public override void OnEpisodeBegin()
|
||||
raySensors.UpdateRayInfo(); // update raycast
|
||||
}
|
||||
|
||||
#endregion On episode begin function
|
||||
|
||||
#region Observation sensor function
|
||||
|
||||
public override void CollectObservations(VectorSensor sensor)
|
||||
{
|
||||
//List<float> enemyLDisList = RaySensors.enemyLDisList;// All Enemy Lside Distances
|
||||
@ -91,45 +97,35 @@ public override void CollectObservations(VectorSensor sensor)
|
||||
myObserve[1] = transform.localPosition.y / raySensors.viewDistance;
|
||||
myObserve[2] = transform.localPosition.z / raySensors.viewDistance;
|
||||
myObserve[3] = transform.eulerAngles.y / 360f;**/
|
||||
float obsNum = 0f;
|
||||
float angleInRadians = transform.eulerAngles.y * Mathf.Deg2Rad;
|
||||
myObserve[0] = transform.localPosition.x;
|
||||
myObserve[1] = transform.localPosition.y;
|
||||
myObserve[2] = transform.localPosition.z;
|
||||
myObserve[3] = MathF.Sin(angleInRadians);
|
||||
myObserve[4] = MathF.Cos(angleInRadians);
|
||||
rayTagResult = raySensors.rayTagResult;// 探测用RayTag类型结果 float[](raySensorNum,1)
|
||||
rayTagResultOnehot = raySensors.rayTagResultOneHot; // 探测用RayTagonehot结果 List<int>[](raySensorNum*Tags,1)
|
||||
rayDisResult = raySensors.rayDisResult; // 探测用RayDis距离结果 float[](raySensorNum,1)
|
||||
myObserve[3] = transform.eulerAngles.y / 36f;
|
||||
rayTagResult = raySensors.rayTagResult;// 探测用RayTag结果 float[](raySensorNum,1)
|
||||
rayTagResultOnehot = raySensors.rayTagResultOneHot.ToArray(); // 探测用RayTagonehot结果 List<int>[](raySensorNum*Tags,1)
|
||||
rayDisResult = raySensors.rayDisResult; // 探测用RayDis结果 float[](raySensorNum,1)
|
||||
targetStates = targetController.targetState; // (6) targettype, target x,y,z, firebasesAreaDiameter
|
||||
remainTime = targetController.leftTime;
|
||||
inFireBaseState = targetController.GetInAreaState();
|
||||
inAreaState = targetController.GetInAreaState();
|
||||
agentController.UpdateGunState();
|
||||
//float[] focusEnemyObserve = RaySensors.focusEnemyInfo;// 最近的Enemy情报 float[](3,1) MinEnemyIndex,x,z
|
||||
|
||||
//sensor.AddObservation(allEnemyNum); // 敌人数量 int
|
||||
sensor.AddObservation(targetController.targetState);// (5) targettype, target x,y,z, firebasesAreaDiameter
|
||||
sensor.AddObservation(inFireBaseState); // (1)
|
||||
sensor.AddObservation(targetStates);// (6) targettype, target x,y,z, firebasesAreaDiameter
|
||||
sensor.AddObservation(inAreaState); // (1)
|
||||
sensor.AddObservation(remainTime); // (1)
|
||||
sensor.AddObservation(agentController.gunReadyToggle); // (1) save gun is ready?
|
||||
sensor.AddObservation(myObserve); // (5)自机位置xyz+朝向 float[](5,1)
|
||||
// count observation number
|
||||
obsNum = targetController.targetState.Length+1+1+1+myObserve.Length;
|
||||
Debug.Log(obsNum);
|
||||
if (commonParamCon.oneHotRayTag)
|
||||
sensor.AddObservation(myObserve); // (4)自机位置xyz+朝向 float[](4,1)
|
||||
if (oneHotRayTag)
|
||||
{
|
||||
sensor.AddObservation(rayTagResultOnehot); // 探测用RayTag结果 float[](raySensorNum,1)
|
||||
obsNum += rayTagResultOnehot.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor.AddObservation(rayTagResult);
|
||||
obsNum += rayTagResult.Length;
|
||||
}
|
||||
Debug.Log(obsNum);
|
||||
sensor.AddObservation(rayDisResult); // 探测用RayDis距离结果 float[](raySensorNum,1)
|
||||
obsNum += rayDisResult.Length;
|
||||
envUIController.UpdateStateText(targetController.targetState, inFireBaseState, remainTime, agentController.gunReadyToggle, myObserve, rayTagResultOnehot, rayDisResult);
|
||||
Debug.Log(obsNum);
|
||||
sensor.AddObservation(rayDisResult); // 探测用RayDis结果 float[](raySensorNum,1)
|
||||
envUIController.UpdateStateText(targetStates, inAreaState, remainTime, agentController.gunReadyToggle, myObserve, rayTagResultOnehot, rayDisResult);
|
||||
/*foreach(float aaa in rayDisResult)
|
||||
{
|
||||
Debug.Log(aaa);
|
||||
@ -140,6 +136,10 @@ public override void CollectObservations(VectorSensor sensor)
|
||||
//sensor.AddObservation(remainTime); // RemainTime int
|
||||
}
|
||||
|
||||
#endregion Observation sensor function
|
||||
|
||||
#region Action received function
|
||||
|
||||
public override void OnActionReceived(ActionBuffers actionBuffers)
|
||||
{
|
||||
//获取输入
|
||||
@ -158,27 +158,27 @@ public override void OnActionReceived(ActionBuffers actionBuffers)
|
||||
//判断结束
|
||||
float sceneReward = 0f;
|
||||
float endReward = 0f;
|
||||
(endTypeInt, sceneReward, endReward) = rewardFunction.CheckOverAndRewards();
|
||||
float nowReward = rewardFunction.RewardCalculate(sceneReward + endReward, Mouse_X, Math.Abs(vertical) + Math.Abs(horizontal), mouseShoot);
|
||||
(finishedState, sceneReward, endReward) = targetController.CheckOverAndRewards();
|
||||
float nowRoundReward = agentController.RewardCalculate(sceneReward + endReward, Mouse_X, Math.Abs(vertical) + Math.Abs(horizontal), mouseShoot);
|
||||
if (hudController.chartOn)
|
||||
{
|
||||
envUIController.UpdateChart(nowReward);
|
||||
envUIController.UpdateChart(nowRoundReward);
|
||||
}
|
||||
else
|
||||
{
|
||||
envUIController.RemoveChart();
|
||||
}
|
||||
worldUICon.UpdateChart(targetController.targetType, endTypeInt);
|
||||
//Debug.Log("reward = " + nowReward);
|
||||
if (endTypeInt != (int)TargetController.EndType.Running)
|
||||
//Debug.Log("reward = " + nowRoundReward);
|
||||
if (finishedState != (int)TargetController.EndType.Running)
|
||||
{
|
||||
// Win or lose Finished
|
||||
Debug.Log("Finish reward = " + nowReward);
|
||||
string targetString = Enum.GetName(typeof(Targets), targetController.targetType);
|
||||
switch (endTypeInt)
|
||||
Debug.Log("Finish reward = " + nowRoundReward);
|
||||
EP += 1;
|
||||
string targetString = Enum.GetName(typeof(Targets), targetController.targetTypeInt);
|
||||
switch (finishedState)
|
||||
{
|
||||
case (int)TargetController.EndType.Win:
|
||||
sideChannelController.SendSideChannelMessage("Result", targetString + "|Win");
|
||||
sideChannelController.SendSideChannelMessage("Result",targetString+ "|Win");
|
||||
messageBoxController.PushMessage(
|
||||
new List<string> { "Game Win" },
|
||||
new List<string> { "green" });
|
||||
@ -195,16 +195,21 @@ public override void OnActionReceived(ActionBuffers actionBuffers)
|
||||
Debug.LogWarning("TypeError");
|
||||
break;
|
||||
}
|
||||
SetReward(nowReward);
|
||||
SetReward(nowRoundReward);
|
||||
EndEpisode();
|
||||
}
|
||||
else
|
||||
{
|
||||
// game not over yet
|
||||
step += 1;
|
||||
}
|
||||
SetReward(nowReward);
|
||||
SetReward(nowRoundReward);
|
||||
}
|
||||
|
||||
#endregion Action received function
|
||||
|
||||
#region Heuristic function
|
||||
|
||||
public override void Heuristic(in ActionBuffers actionsOut)
|
||||
{
|
||||
//-------------------BUILD
|
||||
@ -262,4 +267,6 @@ public override void Heuristic(in ActionBuffers actionsOut)
|
||||
//continuousActions[2] = timeLimit;
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^continuous-Control^^^^^^^^^^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
#endregion Heuristic function
|
||||
}
|
@ -3,16 +3,110 @@
|
||||
|
||||
public class ParameterContainer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject targetConObj;
|
||||
[SerializeField] private GameObject blockConObj;
|
||||
[SerializeField] private GameObject agentObj;
|
||||
[SerializeField] private GameObject hudObj;
|
||||
|
||||
public GameObject targetConObj;
|
||||
public GameObject blockConObj;
|
||||
public GameObject agentObj;
|
||||
public GameObject hudObj;
|
||||
private TargetController targetCon;
|
||||
private SceneBlockContainer blockCont;
|
||||
private CommonParameterContainer commonParamCont;
|
||||
private StartSeneData startSceneData;
|
||||
private MessageBoxController messageCon;
|
||||
private float agentDistance;
|
||||
private int agentInArea;
|
||||
|
||||
[Header("Env")]
|
||||
public bool lockMouse = false;
|
||||
|
||||
public float damage = 50; // damage to enemy
|
||||
public float fireRate = 0.5f;
|
||||
public int timeLimit = 30;
|
||||
public bool lockCameraX = false;
|
||||
public bool lockCameraY = true;
|
||||
public bool spawnAgentInAllMap = true;
|
||||
public int spinRecordMax = 40;
|
||||
public float spinPenaltyThreshold = 10;
|
||||
public float facingInviewEnemyDisCOEF = 0.5f;
|
||||
|
||||
[Header("Dynamic Defaut Rewards")]
|
||||
//[Tooltip("Hit Enemy reward")]
|
||||
//public float hitRewardDefault = 60.0f;
|
||||
[Tooltip("Free mode Hit Enemy reward")]
|
||||
public float hitTargetRewardDefault = 25f;
|
||||
|
||||
//[Tooltip("Enemy down reward")]
|
||||
//public float killRewardDefault = 60.0f;
|
||||
[Tooltip("Enemy down in area Reward")]
|
||||
public float killTargetEnemyRewardDefault = 25f;
|
||||
|
||||
[Tooltip("stay in firebasesArea reward")]
|
||||
public float inAreaRewardDefault = 12f;
|
||||
|
||||
[Tooltip("free left time bonus reward. ALLR + leftTime * r")]
|
||||
public float freeTimeBonusPerSec = 1.0f;
|
||||
|
||||
[Tooltip("target left time bonus reward. ALLR + leftTime * r")]
|
||||
public float targetTimeBonusPerSec = 0.5f;
|
||||
|
||||
[Tooltip("in area left time bonus reward. ALLR + leftTime * r")]
|
||||
public float areaTimeBonusPerSec = 0.2f;
|
||||
|
||||
[Tooltip("distance reward reward = r*(1-(nowDis/startDis))")]
|
||||
public float distanceReward = 50.0f;
|
||||
|
||||
[Tooltip("facing to Target distance reward reward = r*(1-(nowDis/startDis))")]
|
||||
public float facingTargetReward = 10.0f;
|
||||
|
||||
[Space(10)]
|
||||
[Tooltip("Goto Win reward")]
|
||||
public float goWinRewardDefault = 999f;
|
||||
|
||||
[Tooltip("Attack Win reward")]
|
||||
public float attackWinRewardDefault = 999f;
|
||||
|
||||
[Tooltip("Defence Win reward")]
|
||||
public float defenceWinRewardDefault = 999f;
|
||||
|
||||
[Tooltip("free Win reward")]
|
||||
public float freeWinRewardDefault = 999f;
|
||||
|
||||
[Header("Static Rewards")]
|
||||
[Tooltip("Nothing happened reward")]
|
||||
public float nonReward = -1f;
|
||||
|
||||
[Tooltip("Episode Lose reward")]
|
||||
public float loseReward = -999f;
|
||||
|
||||
[Tooltip("Agent Do shoot action reward")]
|
||||
public float shootReward = -0.5f;
|
||||
|
||||
[Tooltip("Hit Not target Enemy reward")]
|
||||
public float hitNonTargetReward = -5f;
|
||||
|
||||
[Tooltip("Not Target Enemy down reward")]
|
||||
public float killNonTargetReward = -5f;
|
||||
|
||||
[Tooltip("Agent Do shoot action but gun is not read")]
|
||||
public float shootWithoutReadyReward = -1.15f;
|
||||
|
||||
[Tooltip("Kill bonus reward stack to nothing happend reward")]
|
||||
public float killBonusReward = 0.0f;
|
||||
|
||||
[Tooltip("Facing to enemy's reward")]
|
||||
public float facingReward = 5f;
|
||||
|
||||
[Tooltip("Shoot at target area but didn't hit enemy")]
|
||||
public float shootTargetAreaReward = 10f;
|
||||
|
||||
[Header("Penalty Rewards")]
|
||||
[Tooltip("move Penalty Reward")]
|
||||
public float movePenalty = 0.1f;
|
||||
|
||||
[Tooltip("spiiiiiiin Panalty Reward")]
|
||||
public float spinPenalty = 0.08f;
|
||||
|
||||
[Tooltip("while move mouse a little bit's penalty")]
|
||||
public float mousePenalty = 0.06f;
|
||||
|
||||
[Header("Dynamic Rewards")]
|
||||
[Tooltip("Free mode Hit Enemy reward")]
|
||||
public float hitTargetReward = 60.0f;
|
||||
@ -36,45 +130,63 @@ public class ParameterContainer : MonoBehaviour
|
||||
[Tooltip("free Win reward")]
|
||||
public float freeWinReward = 50.0f;
|
||||
|
||||
[Tooltip("Scene Prefab Set")]
|
||||
public SceneBlocksSet scenePrefabSet;
|
||||
|
||||
private float targetTimeBonus = 0f;
|
||||
private float areaTimeBonus = 0f;
|
||||
private float freeTimeBonus = 0f;
|
||||
private float targetInAreaTime = 0f;
|
||||
private float lastFrameTime = 0f;
|
||||
|
||||
private float areaTimeBonusPerSec;
|
||||
private float freeTimeBonusPerSec;
|
||||
private float targetTimeBonusPerSec;
|
||||
private int timeLimit = 30;
|
||||
[System.NonSerialized] public int gameMode; // 0 = trainning mode, 1 = play mode
|
||||
[System.NonSerialized] public float attackProb = 0f;
|
||||
[System.NonSerialized] public List<float> attackLevelProbs = new List<float>();
|
||||
[System.NonSerialized] public float gotoProb = 0f;
|
||||
[System.NonSerialized] public List<float> gotoLevelProbs = new List<float>();
|
||||
[System.NonSerialized] public float defenceProb = 0f;
|
||||
[System.NonSerialized] public List<float> defenceLevelProbs = new List<float>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
targetCon = targetConObj.GetComponent<TargetController>();
|
||||
blockCont = blockConObj.GetComponent<SceneBlockContainer>();
|
||||
commonParamCont = CommonParameterContainer.Instance;
|
||||
|
||||
areaTimeBonusPerSec = commonParamCont.areaTimeBonusPerSec;
|
||||
freeTimeBonusPerSec = commonParamCont.freeTimeBonusPerSec;
|
||||
targetTimeBonusPerSec = commonParamCont.targetTimeBonusPerSec;
|
||||
timeLimit = commonParamCont.timeLimit;
|
||||
|
||||
messageCon = hudObj.GetComponent<MessageBoxController>();
|
||||
areaTimeBonus = areaTimeBonusPerSec * timeLimit;
|
||||
freeTimeBonus = freeTimeBonusPerSec * timeLimit;
|
||||
targetTimeBonus = targetTimeBonusPerSec * timeLimit;
|
||||
|
||||
// Win Rewards
|
||||
goWinReward = commonParamCont.goWinRewardDefault;
|
||||
attackWinReward = commonParamCont.attackWinRewardDefault;
|
||||
defenceWinReward = commonParamCont.defenceWinRewardDefault;
|
||||
freeWinReward = commonParamCont.freeWinRewardDefault;
|
||||
try
|
||||
{
|
||||
// try get start scene data
|
||||
startSceneData = GameObject.Find("StartSceneDataTransfer").GetComponent<StartSeneData>();
|
||||
messageCon.PushMessage(
|
||||
new List<string> { "ParameterContainer:", "StartSceneDataTransfer found!" },
|
||||
new List<string> { "green", "white" });
|
||||
}
|
||||
catch
|
||||
{
|
||||
// if not found, find dummy StartSeneData
|
||||
startSceneData = GameObject.Find("StartSceneDataTransferDummy").GetComponent<StartSeneData>();
|
||||
messageCon.PushMessage(
|
||||
new List<string> { "ParameterContainer:", "StartSceneDataTransfer not found!Use Dummy." },
|
||||
new List<string> { "orange" });
|
||||
}
|
||||
gameMode = startSceneData.gameMode;
|
||||
attackProb = startSceneData.attackProb;
|
||||
attackLevelProbs = startSceneData.attackLevelProbs;
|
||||
gotoProb = startSceneData.gotoProb;
|
||||
gotoLevelProbs = startSceneData.gotoLevelProbs;
|
||||
defenceProb = startSceneData.defenceProb;
|
||||
defenceLevelProbs = startSceneData.defenceLevelProbs;
|
||||
scenePrefabSet = startSceneData.scenePrefabSet;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// get target distance and in area
|
||||
if (targetCon.targetType is Targets.Go or Targets.Attack)
|
||||
if (targetCon.targetTypeInt is (int)Targets.Go or (int)Targets.Attack)
|
||||
{
|
||||
(_, agentInArea) = blockCont.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
(agentDistance, agentInArea) = blockCont.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
// attack goto or defence target
|
||||
if (agentInArea == 1)
|
||||
{
|
||||
@ -94,9 +206,15 @@ private void Update()
|
||||
targetTimeBonus = targetTimeBonusPerSec * targetCon.leftTime;
|
||||
}
|
||||
|
||||
hitTargetReward = commonParamCont.hitTargetRewardDefault + targetTimeBonus;
|
||||
killTargetEnemyReward = commonParamCont.killTargetEnemyRewardDefault + targetTimeBonus;
|
||||
inAreaReward = commonParamCont.inAreaRewardDefault + areaTimeBonus;
|
||||
hitTargetReward = hitTargetRewardDefault + targetTimeBonus;
|
||||
killTargetEnemyReward = killTargetEnemyRewardDefault + targetTimeBonus;
|
||||
inAreaReward = inAreaRewardDefault + areaTimeBonus;
|
||||
|
||||
// Win Rewards
|
||||
goWinReward = goWinRewardDefault;
|
||||
attackWinReward = attackWinRewardDefault;
|
||||
defenceWinReward = defenceWinRewardDefault;
|
||||
freeWinReward = freeWinRewardDefault;
|
||||
}
|
||||
|
||||
public void ResetTimeBonusReward()
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
public class RaySensors : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Camera agentCam;
|
||||
[SerializeField] private Camera TPSCam;
|
||||
[SerializeField] private Material lineMeterial;
|
||||
[SerializeField] private GameObject rayInfoPrefab;
|
||||
[SerializeField] private GameObject agentCanvas;
|
||||
public Camera agentCam;
|
||||
public Camera TPSCam;
|
||||
public Material lineMeterial;
|
||||
public GameObject rayInfoPrefab;
|
||||
public GameObject agentCanvas;
|
||||
|
||||
[SerializeField, Range(0, 500)] public float viewDistance = 100; // how long the ray can detect
|
||||
|
||||
@ -30,7 +30,7 @@ public class RaySensors : MonoBehaviour
|
||||
[Header("RayCastResult")]
|
||||
public float[] rayTagResult;
|
||||
|
||||
public float[] rayTagResultOneHot;
|
||||
public List<float> rayTagResultOneHot;
|
||||
public float[] rayDisResult;
|
||||
|
||||
[System.NonSerialized] public int totalRayNum;
|
||||
@ -49,7 +49,6 @@ private void Start()
|
||||
totalRayNum = halfOuterRayNum * 2 + focusRayNum;
|
||||
rayTagResult = new float[totalRayNum];
|
||||
rayDisResult = new float[totalRayNum];
|
||||
rayTagResultOneHot = new float[totalRayNum*ObjectTags.Tags.Count];
|
||||
linesOBJ = new GameObject[totalRayNum];
|
||||
lineRenderers = new LineRenderer[totalRayNum];
|
||||
rayInfoOBJ = new GameObject[totalRayNum];
|
||||
@ -71,60 +70,85 @@ private void Start()
|
||||
}
|
||||
}
|
||||
|
||||
private void SingleRaycastUpdate(Ray ray,int rayIndex)
|
||||
public int TagToInt(string tag)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case "Wall":
|
||||
return 1;
|
||||
|
||||
default:
|
||||
if (tag != myTag)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void SingleRaycastUpdate(Ray ray, LineRenderer lineRenderer, RayInfoUI rayInfoUI, out float rayTagResult, out float rayDisResult)
|
||||
{
|
||||
// get Raycast hit infomation and return Tag and distance
|
||||
RaycastHit nowHit;
|
||||
Color rayColor = Color.gray;
|
||||
Color rayColor = Color.cyan;
|
||||
float lineLength = viewDistance;
|
||||
string rayInfoText = "";
|
||||
Vector3 rayInfoPosition;
|
||||
if (Physics.Raycast(ray, out nowHit, viewDistance)) // 若在viewDistance范围内有碰撞
|
||||
{
|
||||
// Tag
|
||||
string thisTag = nowHit.collider.tag;
|
||||
// result update
|
||||
rayTagResult[rayIndex] = ObjectTags.TagToInt(thisTag);
|
||||
rayDisResult[rayIndex] = nowHit.distance;
|
||||
int oneHotIndex = rayIndex * ObjectTags.Tags.Count + ObjectTags.TagToInt(thisTag);
|
||||
rayTagResultOneHot[oneHotIndex] = 1f;
|
||||
if (rayTagResult[rayIndex] == ObjectTags.TagToInt("Enemy"))
|
||||
rayInfoText = nowHit.collider.tag;
|
||||
rayTagResult = TagToInt(rayInfoText);
|
||||
rayTagResultOneHot.AddRange(oneHotTags.Encoder(rayInfoText));
|
||||
rayDisResult = nowHit.distance;
|
||||
lineLength = rayDisResult;
|
||||
rayInfoText += "\n" + Convert.ToString(rayDisResult);
|
||||
// rayDisResult = rayDisResult / viewDistance; // Normalization!
|
||||
// 输出log
|
||||
switch (rayTagResult)
|
||||
{
|
||||
inViewEnemies.Add(nowHit.transform.gameObject);
|
||||
case 1:// Wall
|
||||
rayColor = Color.white;
|
||||
break;
|
||||
|
||||
case 2: // Enemy
|
||||
rayColor = Color.red;
|
||||
inViewEnemies.Add(nowHit.transform.gameObject);
|
||||
break;
|
||||
|
||||
case -1: // Hit Nothing
|
||||
rayColor = Color.gray;
|
||||
break;
|
||||
|
||||
default: // default,got wrong
|
||||
rayColor = Color.cyan;
|
||||
break;
|
||||
}
|
||||
// ingame info update
|
||||
lineLength = nowHit.distance;
|
||||
rayInfoText = thisTag + "\n" + Convert.ToString(nowHit.distance);
|
||||
rayColor = ObjectTags.TagToCololr(thisTag);
|
||||
|
||||
}
|
||||
else // 若在viewDistance范围无碰撞
|
||||
{
|
||||
// Result update
|
||||
// rayTagResultOneHot keep zero
|
||||
rayTagResult[rayIndex] = -1;
|
||||
rayDisResult[rayIndex] = -1;
|
||||
// Info
|
||||
rayInfoText = "Empty";
|
||||
rayTagResultOneHot.AddRange(oneHotTags.Encoder());
|
||||
rayTagResult = -1f;
|
||||
rayDisResult = -1f;
|
||||
//输出log
|
||||
//Debug.Log(0);
|
||||
//Debug.Log(0);
|
||||
}
|
||||
|
||||
// draw Info In Game
|
||||
rayInfoPosition = ray.origin + (ray.direction * lineLength);
|
||||
if (showInGameRay)
|
||||
{
|
||||
DrawLine(ray, lineLength, lineRenderers[rayIndex], rayColor);
|
||||
DrawLine(ray, lineLength, lineRenderer, rayColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOffLine(lineRenderers[rayIndex], rayColor);
|
||||
TurnOffLine(lineRenderer, rayColor);
|
||||
}
|
||||
// drawRay in game
|
||||
if (showInGameRayInfo) rayInfoUIs[rayIndex].UpdateInfo(rayInfoText, rayInfoPosition, rayColor, TPSCam);
|
||||
if (showInGameRayInfo) rayInfoUI.UpdateInfo(rayInfoText, rayInfoPosition, rayColor, TPSCam);
|
||||
// Show log
|
||||
if (showDebugRay) Debug.DrawRay(ray.origin, ray.direction * viewDistance, rayColor); // drawRay in debug
|
||||
// Debug.Log(ray.origin + ray.direction);
|
||||
// Debug.Log(thisRayTagResult);
|
||||
// Debug.Log(tagToInt(nowHit.collider.thisTag));
|
||||
// Debug.Log(rayTagResult);
|
||||
// Debug.Log(tagToInt(nowHit.collider.tag));
|
||||
}
|
||||
|
||||
private void DrawLine(Ray ray, float lineLength, LineRenderer lineRenderer, Color lineColor)
|
||||
@ -153,31 +177,24 @@ public void UpdateRayInfo()
|
||||
float focusREdge = agentCam.pixelWidth * (1 + focusRange) / 2;
|
||||
float camPixelHeight = agentCam.pixelHeight;
|
||||
inViewEnemies.Clear();
|
||||
ClearResult();
|
||||
rayTagResultOneHot.Clear();
|
||||
for (int i = 0; i < halfOuterRayNum; i++) // create left outside rays; 0 ~ focusLeftEdge
|
||||
{
|
||||
Vector3 point = new Vector3(i * focusLEdge / (halfOuterRayNum - 1), camPixelHeight / 2, 0);
|
||||
Ray nowRay = agentCam.ScreenPointToRay(point);
|
||||
SingleRaycastUpdate(nowRay,i);
|
||||
SingleRaycastUpdate(nowRay, lineRenderers[i], rayInfoUIs[i], out rayTagResult[i], out rayDisResult[i]);
|
||||
}
|
||||
for (int i = 0; i < halfOuterRayNum; i++) // create right outside rays; focusRightEdge ~ MaxPixelHeight
|
||||
{
|
||||
Vector3 point = new Vector3(focusREdge + (i * focusLEdge / (halfOuterRayNum - 1)), camPixelHeight / 2, 0);
|
||||
Ray nowRay = agentCam.ScreenPointToRay(point);
|
||||
SingleRaycastUpdate(nowRay, halfOuterRayNum + i);
|
||||
SingleRaycastUpdate(nowRay, lineRenderers[halfOuterRayNum + i], rayInfoUIs[halfOuterRayNum + i], out rayTagResult[halfOuterRayNum + i], out rayDisResult[halfOuterRayNum + i]);
|
||||
}
|
||||
for (int i = 0; i < focusRayNum; i++) // create center focus rays; focusLeftEdge ~ focusLeftEdge
|
||||
{
|
||||
Vector3 point = new Vector3(focusLEdge + ((i + 1) * (focusREdge - focusLEdge) / (focusRayNum + 1)), camPixelHeight / 2, 0);
|
||||
Ray nowRay = agentCam.ScreenPointToRay(point);
|
||||
SingleRaycastUpdate(nowRay, halfOuterRayNum * 2 + i);
|
||||
SingleRaycastUpdate(nowRay, lineRenderers[halfOuterRayNum * 2 + i], rayInfoUIs[halfOuterRayNum * 2 + i], out rayTagResult[halfOuterRayNum * 2 + i], out rayDisResult[halfOuterRayNum * 2 + i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearResult()
|
||||
{
|
||||
rayTagResult = new float[totalRayNum];
|
||||
rayDisResult = new float[totalRayNum];
|
||||
rayTagResultOneHot = new float[totalRayNum * ObjectTags.Tags.Count];
|
||||
}
|
||||
}
|
@ -1,615 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class RewardFunction : MonoBehaviour
|
||||
{
|
||||
public enum EndType
|
||||
{ Win, Lose, Running, Num };
|
||||
|
||||
[SerializeField] private GameObject parameterContainerObj;
|
||||
[SerializeField] private GameObject sceneBlockContainerObj;
|
||||
[SerializeField] private GameObject targetControllerObj;
|
||||
[SerializeField] private GameObject environmentUIObj;
|
||||
[SerializeField] private GameObject enemyContainerObj;
|
||||
|
||||
private GameObject agentObj;
|
||||
private Camera fpsCam;
|
||||
private CommonParameterContainer commonParamCon;
|
||||
private SceneBlockContainer sceneBlockCon;
|
||||
private ParameterContainer paramCon;
|
||||
private TargetController targetCon;
|
||||
private EnvironmentUIControl envUICon;
|
||||
private AgentController agentCon;
|
||||
private RaySensors raySensors;
|
||||
|
||||
private bool firstRewardFlag = false;
|
||||
private float lastDistance;
|
||||
private float lastEnemyFacingDistance = 0f; // record last enemy facing minimum distance
|
||||
private float lastTargetFacingDistance = 0f; // record last target facing minimum distance
|
||||
private List<float> spinRecord = new List<float>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
agentObj = gameObject;
|
||||
agentCon = agentObj.GetComponent<AgentController>();
|
||||
fpsCam = agentCon.fpsCam;
|
||||
commonParamCon = CommonParameterContainer.Instance;
|
||||
paramCon = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
sceneBlockCon = sceneBlockContainerObj.GetComponent<SceneBlockContainer>();
|
||||
targetCon = targetControllerObj.GetComponent<TargetController>();
|
||||
envUICon = environmentUIObj.GetComponent<EnvironmentUIControl>();
|
||||
raySensors = GetComponent<RaySensors>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the reward value.
|
||||
/// </summary>
|
||||
/// <param name="sceneReward">Reward value from the scene.</param>
|
||||
/// <param name="mouseX">Movement amount of the mouse along the X-axis.</param>
|
||||
/// <param name="movement">Movement of discrete.</param>
|
||||
/// <param name="shootState">State of the shooting action.</param>
|
||||
/// <returns>Returns the calculated total reward value.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the total reward based on the provided parameters,
|
||||
/// taking into account rewards for enemy kills, shooting actions, facing reward,
|
||||
/// and penalties such as spin and movement.
|
||||
/// </remarks>
|
||||
public float RewardCalculate(float sceneReward, float mouseX, float movement, int shootState)
|
||||
{
|
||||
float epreward = 0f;
|
||||
// Got kill point reward
|
||||
if (agentCon.enemyKillCount > 0)
|
||||
{
|
||||
for (int i = 0; i < agentCon.enemyKillCount; i++)
|
||||
{
|
||||
// get
|
||||
epreward += KillReward(agentCon.killEnemyPosition);
|
||||
}
|
||||
agentCon.enemyKillCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
agentCon.enemyKillCount = 0;
|
||||
}
|
||||
// Shoot action reward
|
||||
epreward += Ballistic(shootState) + sceneReward;
|
||||
// facing reward
|
||||
epreward += FacingReward();
|
||||
// Penalty
|
||||
// spin penalty
|
||||
spinRecord.Add(mouseX);
|
||||
if (spinRecord.Count >= commonParamCon.spinRecordMax)
|
||||
{
|
||||
spinRecord.RemoveAt(0);
|
||||
}
|
||||
float spinPenaltyReward = Math.Abs(spinRecord.ToArray().Sum() * commonParamCon.spinPenalty);
|
||||
if (spinPenaltyReward >= commonParamCon.spinPenaltyThreshold)
|
||||
{
|
||||
epreward -= spinPenaltyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
epreward -= Math.Abs(mouseX) * commonParamCon.mousePenalty;
|
||||
}
|
||||
// move penalty
|
||||
if (movement != 0)
|
||||
{
|
||||
epreward -= commonParamCon.movePenalty;
|
||||
}
|
||||
return epreward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the reward value for shooting actions.
|
||||
/// </summary>
|
||||
/// <param name="shootState">State value of the shooting action.</param>
|
||||
/// <returns>Returns the reward value associated with shooting.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the reward value based on the shooting state and other related conditions,
|
||||
/// such as whether the enemy was hit, whether the shot was towards the target area, and whether the gun was ready to shoot.
|
||||
/// </remarks>
|
||||
private float Ballistic(int shootState)
|
||||
{
|
||||
Vector3 point = new Vector3(fpsCam.pixelWidth / 2, fpsCam.pixelHeight / 2, 0);// start position
|
||||
Ray ray = fpsCam.ScreenPointToRay(point);
|
||||
RaycastHit hit;
|
||||
// Debug.DrawRay(centerRay.origin, centerRay.direction * 100, Color.blue);
|
||||
// Mouse Pressed
|
||||
if (shootState != 0 && agentCon.gunReadyToggle == true)
|
||||
{
|
||||
agentCon.lastShootTime = Time.time;
|
||||
if (Physics.Raycast(ray, out hit, 100))
|
||||
{
|
||||
if (hit.collider.tag != agentCon.myTag && hit.collider.tag != "Wall" && hit.collider.tag != "Untagged")
|
||||
{
|
||||
// kill enemy
|
||||
GameObject gotHitObj = hit.transform.gameObject;
|
||||
gotHitObj.GetComponent<States>().ReactToHit(commonParamCon.damage, gameObject);
|
||||
shootState = 0;
|
||||
return HitEnemyReward(gotHitObj.transform.position);
|
||||
}
|
||||
}
|
||||
if (targetCon.targetType == Targets.Attack)
|
||||
{
|
||||
// while if attack mode
|
||||
float targetDis = Vector3.Distance(sceneBlockCon.nowBlock.transform.position, transform.position);
|
||||
if (targetDis <= raySensors.viewDistance)
|
||||
{
|
||||
// Debug.DrawRay(new Vector3(0,0,0), viewPoint, Color.red);
|
||||
if (Vector3.Distance(ray.origin + (ray.direction * targetDis), sceneBlockCon.nowBlock.transform.position) <= sceneBlockCon.nowBlock.firebasesAreaDiameter / 2)
|
||||
{
|
||||
// im shooting at target but didn't hit enemy
|
||||
// Debug.DrawRay(centerRay.origin, viewPoint-centerRay.origin, Color.blue);
|
||||
return commonParamCon.shootTargetAreaReward;
|
||||
}
|
||||
}
|
||||
}
|
||||
shootState = 0;
|
||||
return commonParamCon.shootReward;
|
||||
}
|
||||
else if (shootState != 0 && agentCon.gunReadyToggle == false)
|
||||
{
|
||||
// shoot without ready
|
||||
shootState = 0;
|
||||
return commonParamCon.shootWithoutReadyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do not shoot
|
||||
shootState = 0;
|
||||
return commonParamCon.nonReward;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the reward value based on the character's facing direction.
|
||||
/// </summary>
|
||||
/// <returns>Returns the reward value for the facing direction.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates a reward value based on the relationship between the character's facing direction and the target.
|
||||
/// in free mode, if the character is facing an enemy, the reward is a fixed value
|
||||
/// in attack mode, the reward depends on the distance between the character and the target, among other factors.
|
||||
/// </remarks>
|
||||
private float FacingReward()
|
||||
{
|
||||
Vector3 screenCenter = new Vector3(fpsCam.pixelWidth / 2, fpsCam.pixelHeight / 2, 0);
|
||||
Vector3 screenLeft = new Vector3(0, fpsCam.pixelHeight / 2, 0);
|
||||
|
||||
Ray centerRay = fpsCam.ScreenPointToRay(screenCenter);
|
||||
Ray leftRay = fpsCam.ScreenPointToRay(screenLeft);
|
||||
|
||||
switch (targetCon.targetType)
|
||||
{
|
||||
case Targets.Free:
|
||||
return FacingRewardFree(centerRay);
|
||||
|
||||
case Targets.Attack:
|
||||
return FacingRewardAttack(centerRay, leftRay);
|
||||
|
||||
case Targets.Go:
|
||||
return FacingRewardGo(centerRay, leftRay);
|
||||
|
||||
case Targets.Stay:
|
||||
// stay mode has no facing reward
|
||||
return 0f;
|
||||
|
||||
default:
|
||||
Debug.LogError("Wrong target type");
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float FacingRewardFree(Ray centerRay)
|
||||
{
|
||||
float nowReward = 0;
|
||||
float enemyFacingDistance = 0f;
|
||||
bool isFacingtoEnemy = false;
|
||||
RaycastHit hit;
|
||||
if (Physics.Raycast(centerRay, out hit, 100))
|
||||
{
|
||||
// facing to an enemy
|
||||
if (hit.collider.tag != agentCon.myTag && hit.collider.tag != "Wall")
|
||||
{
|
||||
nowReward = commonParamCon.facingReward;
|
||||
isFacingtoEnemy = true;
|
||||
}
|
||||
}
|
||||
if (raySensors.inViewEnemies.Count > 0 && !isFacingtoEnemy)
|
||||
{
|
||||
// have enemy in view
|
||||
List<float> projectionDis = new List<float>();
|
||||
foreach (GameObject theEnemy in raySensors.inViewEnemies)
|
||||
{
|
||||
// for each enemy in view
|
||||
Vector3 projection = Vector3.Project(theEnemy.transform.position - transform.position, (centerRay.direction * 10));
|
||||
Vector3 verticalToRay = transform.position + projection - theEnemy.transform.position;
|
||||
projectionDis.Add(verticalToRay.magnitude);
|
||||
// Debug.Log("enemy!" + verticalToRay.magnitude);
|
||||
// Debug.DrawRay(transform.position, (centerRay.direction * 100), Color.cyan);
|
||||
// Debug.DrawRay(transform.position, theEnemy.transform.position - transform.position, Color.yellow);
|
||||
// Debug.DrawRay(transform.position, projection, Color.blue);
|
||||
// Debug.DrawRay(theEnemy.transform.position, verticalToRay, Color.magenta);
|
||||
}
|
||||
enemyFacingDistance = projectionDis.Min();
|
||||
if (enemyFacingDistance <= lastEnemyFacingDistance)
|
||||
{
|
||||
// closing to enemy
|
||||
nowReward = 1 / MathF.Sqrt(commonParamCon.facingInviewEnemyDisCOEF * enemyFacingDistance + 0.00001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
nowReward = 0;
|
||||
}
|
||||
// enemy in view Reward
|
||||
lastEnemyFacingDistance = enemyFacingDistance;
|
||||
if (nowReward >= commonParamCon.facingReward) nowReward = commonParamCon.facingReward; // limit
|
||||
if (nowReward <= -commonParamCon.facingReward) nowReward = -commonParamCon.facingReward; // limit
|
||||
// Debug.Log("ninimum = " + nowReward);
|
||||
}
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
private float FacingRewardGo(Ray centerRay, Ray leftRay)
|
||||
{
|
||||
float nowReward = 0;
|
||||
float camCenterToFireBase;
|
||||
float camCenterToViewEdge;
|
||||
(camCenterToFireBase, camCenterToViewEdge, _) = CameraCenterToFireBaseAndViewEdge(centerRay, leftRay);
|
||||
|
||||
// goto mode
|
||||
if (camCenterToFireBase <= camCenterToViewEdge)
|
||||
{
|
||||
// fireArea is in view
|
||||
nowReward = commonParamCon.facingReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
nowReward = 0;
|
||||
}
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
private float FacingRewardAttack(Ray centerRay, Ray leftRay)
|
||||
{
|
||||
float nowReward = 0;
|
||||
float camCenterToFireBase;
|
||||
float targetDis;
|
||||
(camCenterToFireBase, _, targetDis) = CameraCenterToFireBaseAndViewEdge(centerRay, leftRay);
|
||||
// attack mode
|
||||
if (targetDis <= raySensors.viewDistance)
|
||||
{
|
||||
// Debug.DrawRay(new Vector3(0,0,0), viewPoint, Color.red);
|
||||
// while center of screen between target's distance is lower than firebasesAreaDiameter
|
||||
// while facing to target
|
||||
if (camCenterToFireBase <= sceneBlockCon.nowBlock.firebasesAreaDiameter / 2)
|
||||
{
|
||||
// Debug.DrawRay(centerRay.origin, viewPoint-centerRay.origin, Color.blue);
|
||||
nowReward = commonParamCon.facingReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// while not facing to target
|
||||
nowReward = (lastTargetFacingDistance - camCenterToFireBase) * commonParamCon.facingTargetReward;
|
||||
}
|
||||
}
|
||||
// update lastTargetFacingDistance
|
||||
lastTargetFacingDistance = camCenterToFireBase;
|
||||
return nowReward;
|
||||
}
|
||||
|
||||
private (float, float, float) CameraCenterToFireBaseAndViewEdge(Ray centerRay, Ray leftRay)
|
||||
{
|
||||
// target fireBaseArea Position, turen y to camera's y
|
||||
Vector3 fireBaseArea = sceneBlockCon.nowBlock.fireBasesAreaObj.transform.position;
|
||||
fireBaseArea.y = fpsCam.transform.position.y;
|
||||
|
||||
// my position, turn y to camera's y
|
||||
// Debug.DrawRay(fpsCam.transform.position, centerRay.direction * 100, Color.blue);
|
||||
Vector3 myposition = transform.position;
|
||||
myposition.y = fpsCam.transform.position.y;
|
||||
|
||||
// Target to Agent distance
|
||||
//Debug.DrawLine(fireBaseArea, myposition, Color.red);
|
||||
float targetDis = Vector3.Distance(fireBaseArea, myposition);
|
||||
|
||||
// point in centerRay and leftRay which distance is targetDis from camera center
|
||||
Vector3 pointInCenterRay = fpsCam.transform.position + (centerRay.direction * targetDis);
|
||||
Vector3 pointInLeftRay = fpsCam.transform.position + (leftRay.direction * targetDis);
|
||||
|
||||
// center of screen to target's distance
|
||||
// Debug.DrawLine(pointInCenterRay, fireBaseArea,Color.green);
|
||||
float camCenterToFireBase = Vector3.Distance(pointInCenterRay, fireBaseArea);
|
||||
|
||||
// left of screen to target's distance
|
||||
// Debug.DrawLine(pointInLeftRay, pointInCenterRay, Color.yellow);
|
||||
float camCenterToViewEdge = Vector3.Distance(pointInLeftRay, pointInCenterRay);
|
||||
return (camCenterToFireBase, camCenterToViewEdge, targetDis);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the game's end state and retrieves rewards.
|
||||
/// </summary>
|
||||
/// <returns>A tuple containing the game's end type, current reward, and final reward.
|
||||
/// 1 = success,2 = overtime,0 = notover</returns>
|
||||
public (int, float, float) CheckOverAndRewards()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
switch (targetCon.targetType)
|
||||
{
|
||||
case Targets.Go:
|
||||
// goto
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsGo();
|
||||
break;
|
||||
|
||||
case Targets.Attack:
|
||||
// attack
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsAttack();
|
||||
break;
|
||||
|
||||
case Targets.Defence:
|
||||
//defence
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsDefence();
|
||||
break;
|
||||
|
||||
case Targets.Stay:
|
||||
// Stay
|
||||
// endless
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
break;
|
||||
|
||||
default:
|
||||
//free kill
|
||||
(endTypeInt, nowReward, endReward) = CheckOverAndRewardsFreeKill();
|
||||
break;
|
||||
}
|
||||
envUICon.ShowResult(endTypeInt);
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsGo()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0;
|
||||
|
||||
(nowDistance, targetCon.inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
float areaTargetReward = GetDistanceReward(nowDistance, targetCon.inArea);
|
||||
//if(inArea != 0)
|
||||
if (sceneBlockCon.nowBlock.firebasesBelong >= sceneBlockCon.nowBlock.belongMaxPoint)
|
||||
{
|
||||
// win
|
||||
// let the area belongs to me
|
||||
nowReward = areaTargetReward;
|
||||
endReward = paramCon.goWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (targetCon.leftTime <= 0)
|
||||
{
|
||||
// time out lose
|
||||
nowReward = areaTargetReward;
|
||||
endReward = commonParamCon.loseReward;
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
nowReward = areaTargetReward;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsAttack()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0;
|
||||
(nowDistance, targetCon.inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
if (sceneBlockCon.nowBlock.GetInAreaNumber(commonParamCon.group2Tag) <= 0 && targetCon.targetEnemySpawnFinish)
|
||||
{
|
||||
// win
|
||||
// let the area belongs to me and kill every enmy in this area.
|
||||
nowReward = 0;
|
||||
endReward = paramCon.attackWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
targetCon.targetEnemySpawnFinish = false;
|
||||
}
|
||||
else if (targetCon.leftTime <= 0 && targetCon.targetEnemySpawnFinish)
|
||||
{
|
||||
// time out lose
|
||||
nowReward = 0;
|
||||
endReward = commonParamCon.loseReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
targetCon.targetEnemySpawnFinish = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
// nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
targetCon.targetEnemySpawnFinish = true;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsDefence()
|
||||
{
|
||||
// !!! NOT FINISHED YET!!!
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0;
|
||||
(nowDistance, targetCon.inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
if (targetCon.leftTime <= 0 && sceneBlockCon.nowBlock.firebasesBelong >= 0f)
|
||||
{
|
||||
// win
|
||||
// time over and the area still mine
|
||||
nowReward = paramCon.defenceWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (sceneBlockCon.nowBlock.firebasesBelong <= sceneBlockCon.nowBlock.belongMaxPoint)
|
||||
{
|
||||
// lost area lose
|
||||
nowReward = commonParamCon.loseReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
// nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
private (int, float, float) CheckOverAndRewardsFreeKill()
|
||||
{
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
if (enemyContainerObj.transform.childCount <= 0)
|
||||
{
|
||||
// win
|
||||
// nowReward = paramCon.winReward + (paramCon.timeBonusPerSecReward * leftTime);
|
||||
nowReward = 0;
|
||||
endReward = paramCon.freeWinReward;
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (targetCon.leftTime <= 0)
|
||||
{
|
||||
// lose
|
||||
//nowReward = paramCon.loseReward;
|
||||
nowReward = 0;
|
||||
endReward = commonParamCon.loseReward;
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates scene reward based on distance, granting higher rewards for being closer to the target.
|
||||
/// </summary>
|
||||
/// <param name="nowDistance">The current distance.</param>
|
||||
/// <param name="inarea">Whether inside an area.</param>
|
||||
/// <returns>The reward value calculated based on distance.</returns>
|
||||
private float GetDistanceReward(float nowDistance, int inarea)
|
||||
{
|
||||
if (firstRewardFlag)
|
||||
{
|
||||
// first distance record
|
||||
(lastDistance, _) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
firstRewardFlag = false;
|
||||
}
|
||||
float nowSeneReward = 0f;
|
||||
if (inarea != 0)
|
||||
{
|
||||
// in area
|
||||
nowSeneReward = paramCon.inAreaReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// out of area
|
||||
// nowSeneReward = paramCon.distanceReward * Math.Clamp(lastDistance - nowDistance, 0, 100);
|
||||
nowSeneReward = commonParamCon.distanceReward * (lastDistance - nowDistance);
|
||||
}
|
||||
lastDistance = nowDistance;
|
||||
return nowSeneReward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates kill reward based on the position of the killed enemy.
|
||||
/// </summary>
|
||||
/// <param name="enemyPosition">The position of the killed enemy.</param>
|
||||
/// <returns>The reward value calculated based on the kill position.</returns>
|
||||
public float KillReward(Vector3 enemyPosition)
|
||||
{
|
||||
float nowKillReward = 0f;
|
||||
if (targetCon.targetType == Targets.Attack)
|
||||
{
|
||||
// attack mode
|
||||
(_, int isInArea) = sceneBlockCon.nowBlock.GetDistInArea(enemyPosition);
|
||||
if (isInArea == 1)
|
||||
{
|
||||
// kill in area enemy
|
||||
nowKillReward = paramCon.killTargetEnemyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
nowKillReward = commonParamCon.killNonTargetReward;
|
||||
}
|
||||
}
|
||||
else if (targetCon.targetType == Targets.Free)
|
||||
{
|
||||
// free mode hit
|
||||
nowKillReward = paramCon.killTargetEnemyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goto & defence
|
||||
nowKillReward = commonParamCon.killNonTargetReward;
|
||||
}
|
||||
return nowKillReward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates hit reward based on the position of the hit enemy and the current mode.
|
||||
/// </summary>
|
||||
/// <param name="enemyPosition">The position of the hit enemy.</param>
|
||||
/// <returns>The reward value calculated based on the hit position and mode.</returns>
|
||||
public float HitEnemyReward(Vector3 enemyPosition)
|
||||
{
|
||||
float nowHitReward = 0f;
|
||||
if (targetCon.targetType == Targets.Attack)
|
||||
{
|
||||
// attack mode
|
||||
(_, int isInArea) = sceneBlockCon.nowBlock.GetDistInArea(enemyPosition);
|
||||
if (isInArea == 1)
|
||||
{
|
||||
// hit in area enemy
|
||||
nowHitReward = paramCon.hitTargetReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hit not in area enemy
|
||||
nowHitReward = commonParamCon.hitNonTargetReward;
|
||||
}
|
||||
}
|
||||
else if (targetCon.targetType == Targets.Free)
|
||||
{
|
||||
// free mode hit
|
||||
nowHitReward = paramCon.hitTargetReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goto & defence
|
||||
nowHitReward = commonParamCon.hitNonTargetReward;
|
||||
}
|
||||
return nowHitReward;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04b45691af6143d4d84b5d024d062bf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -109,7 +109,7 @@ public void InitBlock(GameObject envObj)
|
||||
// Debug.Log("SceneBlock.Start: enemyContainerObj not found, get it by name");
|
||||
enemyContainerObj = transform.Find("EnemyContainer").gameObject;
|
||||
}
|
||||
firebasesAreaPosition = fireBasesAreaObj.transform.position;
|
||||
firebasesAreaPosition = transform.position + fireBasesAreaObj.transform.position;
|
||||
firebasesAreaScale = fireBasesAreaObj.transform.localScale.x;
|
||||
firebasesAreaDiameter = firebasesAreaScale * blockSize;
|
||||
firebasesBelong = -belongMaxPoint;
|
||||
|
@ -2,12 +2,10 @@
|
||||
|
||||
public class SceneBlockContainer : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private float sceneSize = 10f;
|
||||
[SerializeField]
|
||||
private GameObject environmentObj;
|
||||
[SerializeField]
|
||||
private GameObject hudObj;
|
||||
public float sceneSize = 10f;
|
||||
public GameObject environmentObj;
|
||||
public GameObject parameterContainerObj;
|
||||
public GameObject hudObj;
|
||||
|
||||
// public GameObject[] attackBlockPrefabs = new GameObject[1];
|
||||
// public GameObject[] goBlockPrefabs = new GameObject[1];
|
||||
@ -15,11 +13,11 @@ public class SceneBlockContainer : MonoBehaviour
|
||||
|
||||
public SceneBlock nowBlock;
|
||||
private GameObject nowBlockObj;
|
||||
private CommonParameterContainer commonParamCon;
|
||||
private ParameterContainer paramCon;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
commonParamCon = CommonParameterContainer.Instance;
|
||||
paramCon = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -42,7 +40,7 @@ public void CreateNewBlock(Targets targetType, int level, int blockType, Vector3
|
||||
DestroyBlock();
|
||||
}
|
||||
// choose target type
|
||||
nowBlockObj = Instantiate(commonParamCon.scenePrefabSet.GetPrefab(level, blockType, targetType), blockPosition + environmentObj.transform.position, Quaternion.identity, transform);
|
||||
nowBlockObj = Instantiate(paramCon.scenePrefabSet.GetPrefab(level, blockType, targetType), blockPosition + environmentObj.transform.position, Quaternion.identity, transform);
|
||||
nowBlock = nowBlockObj.GetComponent<SceneBlock>();
|
||||
nowBlock.group1Tag = tag1;
|
||||
nowBlock.group2Tag = tag2;
|
||||
|
@ -5,12 +5,14 @@
|
||||
|
||||
public class TargetController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject environmentObj;
|
||||
[SerializeField] private GameObject agentObj;
|
||||
[SerializeField] private GameObject HUDObj;
|
||||
[SerializeField] private GameObject sceneBlockContainerObj;
|
||||
[SerializeField] private GameObject enemyContainerObj;
|
||||
[SerializeField] private GameObject environmentUIObj;
|
||||
public GameObject environmentObj;
|
||||
public GameObject agentObj;
|
||||
public GameObject HUDObj;
|
||||
public GameObject sceneBlockContainerObj;
|
||||
public GameObject enemyContainerObj;
|
||||
public GameObject parameterContainerObj;
|
||||
public GameObject environmentUIObj;
|
||||
public GameObject worldUIObj;
|
||||
|
||||
// area
|
||||
public GameObject edgeUp;
|
||||
@ -20,6 +22,11 @@ public class TargetController : MonoBehaviour
|
||||
public GameObject edgeRight;
|
||||
public GameObject edgeAgent_Enemy;
|
||||
|
||||
//group
|
||||
public string group1Tag = "Player";
|
||||
|
||||
public string group2Tag = "Enemy";
|
||||
|
||||
public float minEnemyAreaX;
|
||||
[System.NonSerialized] public float maxEnemyAreaX;
|
||||
[System.NonSerialized] public float minEnemyAreaZ;
|
||||
@ -35,10 +42,10 @@ public class TargetController : MonoBehaviour
|
||||
[SerializeField, Range(0f, 1f)] public float gotoProb = 0.2f;
|
||||
[SerializeField, Range(0f, 1f)] public float defenceProb = 0.2f;
|
||||
|
||||
[System.NonSerialized] public Targets targetType;
|
||||
[System.NonSerialized] public int targetTypeInt;
|
||||
[System.NonSerialized] public int gotoLevelNum;
|
||||
[System.NonSerialized] public int attackLevelNum;
|
||||
[System.NonSerialized] public float[] targetState = new float[5];
|
||||
public float[] targetState = new float[6];
|
||||
|
||||
public enum EndType
|
||||
{ Win, Lose, Running, Num };
|
||||
@ -46,20 +53,21 @@ public enum EndType
|
||||
[System.NonSerialized] public int targetNum = 0;
|
||||
private Dictionary<int, float[]> oneHotRarget = new Dictionary<int, float[]>();
|
||||
|
||||
private int inArea = 0;
|
||||
private float freeProb;
|
||||
private float sceneBlockSize;
|
||||
private float lastDistance;
|
||||
private int randBlockType = 0;
|
||||
private int randLevel = 0;
|
||||
public int inArea = 0;
|
||||
public Vector3 targetPosition;
|
||||
private bool firstRewardFlag = true;
|
||||
public bool targetEnemySpawnFinish = false;
|
||||
|
||||
private bool targetEnemySpawnFinish = false;
|
||||
private SceneBlockContainer sceneBlockCon;
|
||||
private EnemyContainer enemyCon;
|
||||
private EnvironmentUIControl envUICon;
|
||||
private CommonParameterContainer commonParamCon;
|
||||
private ParameterContainer paramCon;
|
||||
private CharacterController agentCharaCon;
|
||||
private WorldUIController worldUICon;
|
||||
private HUDController hudCon;
|
||||
private MessageBoxController messageBoxCon;
|
||||
|
||||
@ -69,19 +77,20 @@ public enum EndType
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
commonParamCon = CommonParameterContainer.Instance;
|
||||
sceneBlockCon = sceneBlockContainerObj.GetComponent<SceneBlockContainer>();
|
||||
envUICon = environmentUIObj.GetComponent<EnvironmentUIControl>();
|
||||
enemyCon = enemyContainerObj.GetComponent<EnemyContainer>();
|
||||
agentCharaCon = agentObj.GetComponent<CharacterController>();
|
||||
paramCon = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
worldUICon = worldUIObj.GetComponent<WorldUIController>();
|
||||
hudCon = HUDObj.GetComponent<HUDController>();
|
||||
messageBoxCon = HUDObj.GetComponent<MessageBoxController>();
|
||||
|
||||
// get parameter from ParameterContainer
|
||||
gamemode = commonParamCon.gameMode;
|
||||
attackProb = commonParamCon.attackProb;
|
||||
gotoProb = commonParamCon.gotoProb;
|
||||
defenceProb = commonParamCon.defenceProb;
|
||||
gamemode = paramCon.gameMode;
|
||||
attackProb = paramCon.attackProb;
|
||||
gotoProb = paramCon.gotoProb;
|
||||
defenceProb = paramCon.defenceProb;
|
||||
|
||||
// initialize spawn area
|
||||
minEnemyAreaX = edgeLeft.transform.localPosition.x + 1.0f;
|
||||
@ -96,8 +105,8 @@ private void Start()
|
||||
|
||||
freeProb = 1 - attackProb - gotoProb - defenceProb;
|
||||
targetNum = (int)Targets.Num;
|
||||
gotoLevelNum = commonParamCon.scenePrefabSet.GetLevelNumber(Targets.Go);
|
||||
attackLevelNum = commonParamCon.scenePrefabSet.GetLevelNumber(Targets.Attack);
|
||||
gotoLevelNum = paramCon.scenePrefabSet.GetLevelNumber(Targets.Go);
|
||||
attackLevelNum = paramCon.scenePrefabSet.GetLevelNumber(Targets.Attack);
|
||||
if (freeProb < 0)
|
||||
{
|
||||
Debug.LogError("TargetController.Start: target percentage wrong");
|
||||
@ -121,13 +130,13 @@ private void Update()
|
||||
// if gamemode is play, then time will keep paramCon.timeLimit
|
||||
if (gamemode == 1)
|
||||
{
|
||||
leftTime = commonParamCon.timeLimit;
|
||||
leftTime = paramCon.timeLimit;
|
||||
// print out time
|
||||
// Debug.Log("Playing Time: " + leftTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
leftTime = commonParamCon.timeLimit - Time.time + startTime;
|
||||
leftTime = paramCon.timeLimit - Time.time + startTime;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,13 +152,13 @@ private void Update()
|
||||
public void RollNewScene()
|
||||
{
|
||||
startTime = Time.time;// Reset StartTime as now time
|
||||
leftTime = commonParamCon.timeLimit - Time.time + startTime;
|
||||
leftTime = paramCon.timeLimit - Time.time + startTime;
|
||||
float randTargetType = UnityEngine.Random.Range(0f, 1f);
|
||||
if (randTargetType <= gotoProb)
|
||||
{
|
||||
// goto target spawn
|
||||
Debug.Log("GOTO THIS TARGET!");
|
||||
targetType = Targets.Go;
|
||||
targetTypeInt = (int)Targets.Go;
|
||||
RandomSpawnSceneBlock(Targets.Go);
|
||||
// set startDistance
|
||||
firstRewardFlag = true;
|
||||
@ -158,7 +167,7 @@ public void RollNewScene()
|
||||
{
|
||||
// attack target spawn
|
||||
Debug.Log("ATTACK Mode Start");
|
||||
targetType = Targets.Attack;
|
||||
targetTypeInt = (int)Targets.Attack;
|
||||
RandomSpawnSceneBlock(Targets.Attack);
|
||||
// set startDistance
|
||||
firstRewardFlag = true;
|
||||
@ -168,7 +177,7 @@ public void RollNewScene()
|
||||
{
|
||||
// defence target spawn
|
||||
Debug.Log("DEFENCE Mode Start");
|
||||
targetType = Targets.Defence;
|
||||
targetTypeInt = (int)Targets.Defence;
|
||||
RandomSpawnSceneBlock(Targets.Defence);
|
||||
// set startDistance
|
||||
firstRewardFlag = true;
|
||||
@ -176,14 +185,14 @@ public void RollNewScene()
|
||||
else
|
||||
{
|
||||
Debug.Log("Free Mode Start");
|
||||
targetType = Targets.Free;
|
||||
targetTypeInt = (int)Targets.Free;
|
||||
enemyCon.DestroyAllEnemys();
|
||||
enemyCon.RandomInitEnemys(hudCon.enemyNum);
|
||||
MoveAgentToSpwanArea();
|
||||
sceneBlockCon.DestroyBlock();
|
||||
}
|
||||
UpdateTargetStates();
|
||||
envUICon.UpdateTargetType(targetType);
|
||||
envUICon.UpdateTargetType(targetTypeInt);
|
||||
}
|
||||
|
||||
#region Agent Move Method
|
||||
@ -196,7 +205,7 @@ private void MoveAgentToSpwanArea()
|
||||
{
|
||||
float randX = UnityEngine.Random.Range(minAgentAreaX, maxAgentAreaX); ;
|
||||
float randZ = 0f;
|
||||
if (commonParamCon.spawnAgentInAllMap)
|
||||
if (paramCon.spawnAgentInAllMap)
|
||||
{
|
||||
// spawn agent in all around map
|
||||
randZ = UnityEngine.Random.Range(minAgentAreaZ, maxEnemyAreaZ);
|
||||
@ -234,6 +243,8 @@ public void MoveAgentTo(Vector3 position)
|
||||
|
||||
#endregion Agent Move Method
|
||||
|
||||
#region Random SceneBlock Spawn Method
|
||||
|
||||
/// <summary>
|
||||
/// Randomly spawns a scene block based on the target type.
|
||||
/// 根据目标类型随机生成场景块。
|
||||
@ -246,8 +257,8 @@ public void MoveAgentTo(Vector3 position)
|
||||
private void RandomSpawnSceneBlock(Targets targetType)
|
||||
{
|
||||
randLevel = RollRandomLevelIndex(targetType);
|
||||
randBlockType = Random.Range(0, commonParamCon.scenePrefabSet.GetBlockNumber(randLevel,targetType));
|
||||
sceneBlockSize = commonParamCon.scenePrefabSet.GetBlockSize(randLevel, randBlockType, targetType);
|
||||
randBlockType = Random.Range(0, paramCon.scenePrefabSet.GetBlockNumber(randLevel,targetType));
|
||||
sceneBlockSize = paramCon.scenePrefabSet.GetBlockSize(randLevel, randBlockType, targetType);
|
||||
|
||||
float randX = UnityEngine.Random.Range(minEnemyAreaX + sceneBlockSize / 2 + 1f, maxEnemyAreaX - sceneBlockSize / 2 - 1f);
|
||||
float randZ = UnityEngine.Random.Range(minEnemyAreaZ + sceneBlockSize / 2 + 1f, maxEnemyAreaZ - sceneBlockSize / 2 - 1f);
|
||||
@ -255,32 +266,268 @@ private void RandomSpawnSceneBlock(Targets targetType)
|
||||
|
||||
// init scene block
|
||||
sceneBlockCon.DestroyBlock();
|
||||
sceneBlockCon.CreateNewBlock(targetType, randLevel, randBlockType, targetPosition, commonParamCon.group1Tag, commonParamCon.group2Tag);
|
||||
sceneBlockCon.CreateNewBlock(targetType, randLevel, randBlockType, targetPosition, group1Tag, group2Tag);
|
||||
enemyCon.DestroyAllEnemys();
|
||||
enemyCon.RandomInitEnemysExcept(hudCon.enemyNum, targetPosition, sceneBlockSize);
|
||||
sceneBlockCon.nowBlock.InitBlock(environmentObj);
|
||||
}
|
||||
|
||||
#endregion Random SceneBlock Spawn Method
|
||||
|
||||
#region Reward function
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a scene block at a specified position.
|
||||
/// Checks the game's end state and retrieves rewards.
|
||||
/// </summary>
|
||||
/// <param name="targetType">The type of the target, determining the type of block to generate.</param>
|
||||
/// <param name="level">The level of the block, affecting its properties.</param>
|
||||
/// <param name="blockNum">The number of the block, used to distinguish different blocks of the same level.</param>
|
||||
/// <param name="blockPosition">The position of the block in the scene.</param>
|
||||
/// <remarks>
|
||||
/// This method first destroys the current block in the scene, then creates a new block based on the provided parameters and initializes it.
|
||||
/// 'sceneBlockCon' is responsible for managing the creation, destruction, and initialization of scene blocks.
|
||||
/// 'commonParamCon' provides additional parameters required for block creation.
|
||||
/// 'environmentObj' is used during the initialization process of the block.
|
||||
/// </remarks>
|
||||
private void SpawnSceneBlock(Targets targetType, int level,int blockNum, Vector3 blockPosition)
|
||||
/// <returns>A tuple containing the game's end type, current reward, and final reward.
|
||||
/// 1 = success,2 = overtime,0 = notover</returns>
|
||||
public (int, float, float) CheckOverAndRewards()
|
||||
{
|
||||
sceneBlockCon.DestroyBlock();
|
||||
sceneBlockCon.CreateNewBlock(targetType, level, blockNum, blockPosition, commonParamCon.group1Tag, commonParamCon.group2Tag);
|
||||
sceneBlockCon.InitializeBlock(environmentObj);
|
||||
int endTypeInt = 0;
|
||||
float nowReward = 0;
|
||||
float endReward = 0;
|
||||
float nowDistance = 0f;
|
||||
switch (targetTypeInt)
|
||||
{
|
||||
case (int)Targets.Go:
|
||||
// goto
|
||||
(nowDistance, inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
float areaTargetReward = GetDistanceReward(nowDistance, inArea);
|
||||
//if(inArea != 0)
|
||||
if (sceneBlockCon.nowBlock.firebasesBelong >= sceneBlockCon.nowBlock.belongMaxPoint)
|
||||
{
|
||||
// win
|
||||
// let the area belongs to me
|
||||
nowReward = areaTargetReward;
|
||||
endReward = paramCon.goWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (leftTime <= 0)
|
||||
{
|
||||
// time out lose
|
||||
nowReward = areaTargetReward;
|
||||
endReward = paramCon.loseReward;
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
nowReward = areaTargetReward;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
break;
|
||||
|
||||
case (int)Targets.Attack:
|
||||
// attack
|
||||
(nowDistance, inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
if (sceneBlockCon.nowBlock.GetInAreaNumber(group2Tag) <= 0 && targetEnemySpawnFinish)
|
||||
{
|
||||
// win
|
||||
// let the area belongs to me and kill every enmy in this area.
|
||||
nowReward = 0;
|
||||
endReward = paramCon.attackWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
targetEnemySpawnFinish = false;
|
||||
}
|
||||
else if (leftTime <= 0 && targetEnemySpawnFinish)
|
||||
{
|
||||
// time out lose
|
||||
nowReward = 0;
|
||||
endReward = paramCon.loseReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
targetEnemySpawnFinish = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
// nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
targetEnemySpawnFinish = true;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
break;
|
||||
|
||||
case (int)Targets.Defence:
|
||||
//defence
|
||||
// !!! DIDN't FINISH!!!
|
||||
(nowDistance, inArea) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
envUICon.UpdateTargetGauge(sceneBlockCon.nowBlock.firebasesBelong, sceneBlockCon.nowBlock.belongMaxPoint);
|
||||
if (leftTime <= 0 && sceneBlockCon.nowBlock.firebasesBelong >= 0f)
|
||||
{
|
||||
// win
|
||||
// time over and the area still mine
|
||||
nowReward = paramCon.defenceWinReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (sceneBlockCon.nowBlock.firebasesBelong <= sceneBlockCon.nowBlock.belongMaxPoint)
|
||||
{
|
||||
// lost area lose
|
||||
nowReward = paramCon.loseReward;
|
||||
//nowReward = (paramCon.inAreaReward * inArea) + getSceneReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
// nowReward = (paramCon.inAreaReward * inArea) + getDistanceReward(nowDistance);
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
break;
|
||||
|
||||
case (int)Targets.Stay:
|
||||
// Stay
|
||||
// endless
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
break;
|
||||
|
||||
default:
|
||||
//free kill
|
||||
if (enemyContainerObj.transform.childCount <= 0)
|
||||
{
|
||||
// win
|
||||
// nowReward = paramCon.winReward + (paramCon.timeBonusPerSecReward * leftTime);
|
||||
nowReward = 0;
|
||||
endReward = paramCon.freeWinReward;
|
||||
endTypeInt = (int)EndType.Win;
|
||||
}
|
||||
else if (leftTime <= 0)
|
||||
{
|
||||
// lose
|
||||
//nowReward = paramCon.loseReward;
|
||||
nowReward = 0;
|
||||
endReward = paramCon.loseReward;
|
||||
endTypeInt = (int)EndType.Lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep on keeping on!
|
||||
nowReward = 0;
|
||||
endReward = 0;
|
||||
endTypeInt = (int)EndType.Running;
|
||||
}
|
||||
break;
|
||||
}
|
||||
envUICon.ShowResult(endTypeInt);
|
||||
worldUICon.UpdateChart(targetTypeInt, endTypeInt);
|
||||
return (endTypeInt, nowReward, endReward);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates scene reward based on distance, granting higher rewards for being closer to the target.
|
||||
/// 根据距离计算场景奖励,靠近目标则获得更高奖励。
|
||||
/// </summary>
|
||||
/// <param name="nowDistance">The current distance.</param>
|
||||
/// <param name="inarea">Whether inside an area.</param>
|
||||
/// <returns>The reward value calculated based on distance.</returns>
|
||||
private float GetDistanceReward(float nowDistance, int inarea)
|
||||
{
|
||||
if (firstRewardFlag)
|
||||
{
|
||||
// first distance record
|
||||
(lastDistance, _) = sceneBlockCon.GetAgentTargetDistanceAndInside(agentObj.transform.position);
|
||||
firstRewardFlag = false;
|
||||
}
|
||||
float nowSeneReward = 0f;
|
||||
if (inarea != 0)
|
||||
{
|
||||
// in area
|
||||
nowSeneReward = paramCon.inAreaReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// out of area
|
||||
// nowSeneReward = paramCon.distanceReward * Math.Clamp(lastDistance - nowDistance, 0, 100);
|
||||
nowSeneReward = paramCon.distanceReward * (lastDistance - nowDistance);
|
||||
}
|
||||
lastDistance = nowDistance;
|
||||
return nowSeneReward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates kill reward based on the position of the killed enemy.
|
||||
/// 根据击杀的敌人位置计算击杀奖励。
|
||||
/// </summary>
|
||||
/// <param name="enemyPosition">The position of the killed enemy.</param>
|
||||
/// <returns>The reward value calculated based on the kill position.</returns>
|
||||
public float KillReward(Vector3 enemyPosition)
|
||||
{
|
||||
float nowKillReward = 0f;
|
||||
if (targetTypeInt == (int)Targets.Attack)
|
||||
{
|
||||
// attack mode
|
||||
(_, int isInArea) = sceneBlockCon.nowBlock.GetDistInArea(enemyPosition);
|
||||
if (isInArea == 1)
|
||||
{
|
||||
// kill in area enemy
|
||||
nowKillReward = paramCon.killTargetEnemyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
nowKillReward = paramCon.killNonTargetReward;
|
||||
}
|
||||
}
|
||||
else if (targetTypeInt == (int)Targets.Free)
|
||||
{
|
||||
// free mode hit
|
||||
nowKillReward = paramCon.killTargetEnemyReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goto & defence
|
||||
nowKillReward = paramCon.killNonTargetReward;
|
||||
}
|
||||
return nowKillReward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates hit reward based on the position of the hit enemy and the current mode.
|
||||
/// 根据击中的敌人位置和当前模式计算击中Reward。
|
||||
/// </summary>
|
||||
/// <param name="enemyPosition">The position of the hit enemy.</param>
|
||||
/// <returns>The reward value calculated based on the hit position and mode.</returns>
|
||||
public float HitEnemyReward(Vector3 enemyPosition)
|
||||
{
|
||||
float nowHitReward = 0f;
|
||||
if (targetTypeInt == (int)Targets.Attack)
|
||||
{
|
||||
// attack mode
|
||||
(_, int isInArea) = sceneBlockCon.nowBlock.GetDistInArea(enemyPosition);
|
||||
if (isInArea == 1)
|
||||
{
|
||||
// hit in area enemy
|
||||
nowHitReward = paramCon.hitTargetReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hit not in area enemy
|
||||
nowHitReward = paramCon.hitNonTargetReward;
|
||||
}
|
||||
}
|
||||
else if (targetTypeInt == (int)Targets.Free)
|
||||
{
|
||||
// free mode hit
|
||||
nowHitReward = paramCon.hitTargetReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goto & defence
|
||||
nowHitReward = paramCon.hitNonTargetReward;
|
||||
}
|
||||
return nowHitReward;
|
||||
}
|
||||
|
||||
#endregion Reward function
|
||||
|
||||
#region Play Mode Method
|
||||
|
||||
/// <summary>
|
||||
@ -295,40 +542,46 @@ private void SpawnSceneBlock(Targets targetType, int level,int blockNum, Vector3
|
||||
/// 该方法用于初始化游戏播放模式,包括设置目标类型、更新目标状态、更新UI显示、
|
||||
/// 将代理移动到生成区域、销毁所有敌人和场景块。
|
||||
/// </remarks>
|
||||
public void PlayModeInitialize()
|
||||
public void PlayInitialize()
|
||||
{
|
||||
targetType = Targets.Stay;
|
||||
targetTypeInt = (int)Targets.Stay;
|
||||
UpdateTargetStates();
|
||||
envUICon.UpdateTargetType(targetType);
|
||||
envUICon.UpdateTargetType(targetTypeInt);
|
||||
MoveAgentToSpwanArea();
|
||||
enemyCon.DestroyAllEnemys();
|
||||
sceneBlockCon.DestroyBlock();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the target type in play mode and updates the game environment accordingly.
|
||||
/// </summary>
|
||||
/// <param name="newTargetType">The new target type to be set.</param>
|
||||
/// <param name="spawnPosition">Spawn position for scene blocks.</param>
|
||||
/// <param name="level">Level parameter for spawning scene blocks.</param>
|
||||
/// <param name="blockNum">Number of blocks to spawn.</param>
|
||||
/// <remarks>
|
||||
/// This method updates the target type to the specified new target. If a spawn position is provided, it spawns scene blocks at that position
|
||||
/// with the specified level and block number. The target states are then updated based on the new setup. The UI is also refreshed to reflect the new target type.
|
||||
/// </remarks>
|
||||
public void PlayTargetChange(Targets newTargetType, Vector3? spawnPosition = null, int level = 0, int blockNum = 0)
|
||||
// change to attack mode
|
||||
public void AttackModeChange(Vector3 targetPosition)
|
||||
{
|
||||
targetType = newTargetType;
|
||||
if(spawnPosition.HasValue)
|
||||
{
|
||||
SpawnSceneBlock(targetType, level, blockNum, spawnPosition.Value);
|
||||
UpdateTargetStates(spawnPosition.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateTargetStates();
|
||||
}
|
||||
envUICon.UpdateTargetType(targetType);
|
||||
targetTypeInt = (int)Targets.Attack;
|
||||
UpdateTargetStates(targetPosition);
|
||||
envUICon.UpdateTargetType(targetTypeInt);
|
||||
}
|
||||
|
||||
// change to free mode
|
||||
public void FreeModeChange()
|
||||
{
|
||||
targetTypeInt = (int)Targets.Free;
|
||||
UpdateTargetStates();
|
||||
envUICon.UpdateTargetType(targetTypeInt);
|
||||
}
|
||||
|
||||
// change to goto mode
|
||||
public void GotoModeChange(Vector3 targetPosition)
|
||||
{
|
||||
targetTypeInt = (int)Targets.Go;
|
||||
UpdateTargetStates(targetPosition);
|
||||
envUICon.UpdateTargetType(targetTypeInt);
|
||||
}
|
||||
|
||||
// change to stay mode
|
||||
public void StayModeChange()
|
||||
{
|
||||
targetTypeInt = (int)Targets.Stay;
|
||||
UpdateTargetStates();
|
||||
envUICon.UpdateTargetType(targetTypeInt);
|
||||
}
|
||||
|
||||
#endregion Play Mode Method
|
||||
@ -341,12 +594,12 @@ public void PlayTargetChange(Targets newTargetType, Vector3? spawnPosition = nul
|
||||
private void UpdateTargetStates(Vector3? targetPosition = null)
|
||||
{
|
||||
// targettype, x,y,z, firebasesAreaDiameter
|
||||
targetState[0] = (int)targetType;
|
||||
targetState[0] = targetTypeInt;
|
||||
if (targetPosition != null)
|
||||
{
|
||||
this.targetPosition = (Vector3)targetPosition;
|
||||
}
|
||||
if (targetType == (int)Targets.Free || targetType == Targets.Stay)
|
||||
if (targetTypeInt == (int)Targets.Free || targetTypeInt == (int)Targets.Stay)
|
||||
{
|
||||
for (int i = 1; i < targetState.Length; i++)
|
||||
// set target position state to 0
|
||||
@ -354,12 +607,11 @@ private void UpdateTargetStates(Vector3? targetPosition = null)
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 fireBasePosition = sceneBlockCon.nowBlock.firebasesAreaPosition;
|
||||
Vector3 convertedPosition = fireBasePosition - this.transform.position;
|
||||
targetState[1] = convertedPosition.x;
|
||||
targetState[2] = convertedPosition.y;
|
||||
targetState[3] = convertedPosition.z;
|
||||
targetState[1] = this.targetPosition.x;
|
||||
targetState[2] = this.targetPosition.y;
|
||||
targetState[3] = this.targetPosition.z;
|
||||
targetState[4] = sceneBlockCon.nowBlock.firebasesAreaDiameter;
|
||||
targetState[5] = sceneBlockCon.nowBlock.belongRatio;
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,7 +622,7 @@ private void UpdateTargetStates(Vector3? targetPosition = null)
|
||||
/// <returns>The in-area state.</returns>
|
||||
public int GetInAreaState()
|
||||
{
|
||||
if (targetType == Targets.Go)
|
||||
if (targetTypeInt == (int)Targets.Go)
|
||||
{
|
||||
return inArea;
|
||||
}
|
||||
@ -388,9 +640,26 @@ public int GetInAreaState()
|
||||
/// <returns>A random level index.</returns>
|
||||
public int RollRandomLevelIndex(Targets target)
|
||||
{
|
||||
Debug.Log(target);
|
||||
List<float> targetProbs;
|
||||
targetProbs = commonParamCon.levelProbs[target];
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case Targets.Attack:
|
||||
targetProbs = paramCon.attackLevelProbs;
|
||||
break;
|
||||
case Targets.Go:
|
||||
targetProbs = paramCon.gotoLevelProbs;
|
||||
break;
|
||||
case Targets.Defence:
|
||||
targetProbs = paramCon.defenceLevelProbs;
|
||||
break;
|
||||
default:
|
||||
messageBoxCon.PushMessage(
|
||||
new List<string> { "[ERROR]TargetController:RandomLevel", "target type error" },
|
||||
new List<string> { "#800000ff" });
|
||||
Debug.LogWarning("[ERROR]TargetController:RandomLevel:target type error");
|
||||
return -1; // Exit early on default case
|
||||
}
|
||||
|
||||
// sample random level depends on the target probabilities
|
||||
float randomNum = UnityEngine.Random.Range(0f, 1f);
|
||||
@ -406,7 +675,7 @@ public int RollRandomLevelIndex(Targets target)
|
||||
|
||||
// If no level was returned, log an error and return -1
|
||||
messageBoxCon.PushMessage(
|
||||
new List<string> { "[ERROR]TargetController:RollRandomLevelIndex", "level index out of range" },
|
||||
new List<string> { "[ERROR]TargetController:RandomLevel", "level index out of range" },
|
||||
new List<string> { "orange" });
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class ObjectTags
|
||||
{
|
||||
public static List<string> Tags = new List<string>() { "Wall", "Enemy", "Player" };
|
||||
|
||||
public static int TagToInt(string tag)
|
||||
{
|
||||
return Tags.IndexOf(tag);
|
||||
}
|
||||
|
||||
public static Color TagToCololr(string tag)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case "Wall":
|
||||
return Color.white;
|
||||
case "Enemy":
|
||||
return Color.red;
|
||||
case "Player":
|
||||
return Color.green;
|
||||
default:
|
||||
return Color.cyan;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38fdb6190ddd36f448389fc04284710d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -6,28 +6,21 @@ public class MouseInMap : MonoBehaviour
|
||||
public float targetDistanceThreshold = 6f;
|
||||
public float enemyDistanceThreshold = 1f;
|
||||
|
||||
[SerializeField]
|
||||
private Camera playCamera;
|
||||
[SerializeField]
|
||||
private GameObject AgentObj;
|
||||
[SerializeField]
|
||||
private GameObject environmentObj;
|
||||
[SerializeField]
|
||||
private GameObject mousePreviewObj;
|
||||
[SerializeField]
|
||||
private GameObject enemyContainerObj;
|
||||
[SerializeField]
|
||||
private GameObject sceneBlockContainerObj;
|
||||
[SerializeField]
|
||||
private GameObject targetControllerObj;
|
||||
[SerializeField]
|
||||
private GameObject HUDObj;
|
||||
public Camera playCamera;
|
||||
public GameObject AgentObj;
|
||||
public GameObject environmentObj;
|
||||
public GameObject mousePreviewObj;
|
||||
public GameObject enemyContainerObj;
|
||||
public GameObject sceneBlockContainerObj;
|
||||
public GameObject targetControllerObj;
|
||||
public GameObject parameterContainerObj;
|
||||
public GameObject HUDObj;
|
||||
|
||||
private Vector3 nowHitPosition = Vector3.zero;
|
||||
private Vector3 nowHitPositionRelative = Vector3.zero;
|
||||
private LayerMask groundMask;
|
||||
private int blockNum;
|
||||
private CommonParameterContainer commonParamCon;
|
||||
private ParameterContainer paramCon;
|
||||
private GameObject previewModel;
|
||||
private TargetController targetCon;
|
||||
private MousePreview mousePreviewCon;
|
||||
@ -54,7 +47,7 @@ public enum MouseMode
|
||||
|
||||
private void Start()
|
||||
{
|
||||
commonParamCon = CommonParameterContainer.Instance;
|
||||
paramCon = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
groundMask = LayerMask.GetMask("Ground");
|
||||
targetCon = targetControllerObj.GetComponent<TargetController>();
|
||||
mousePreviewCon = mousePreviewObj.GetComponent<MousePreview>();
|
||||
@ -87,7 +80,9 @@ private void Update()
|
||||
else
|
||||
{
|
||||
// if agent or enemy is not nearby, create new block
|
||||
targetCon.PlayTargetChange(Targets.Attack, nowHitPositionRelative, blockLevel, blockNum);
|
||||
sceneBlockCon.CreateNewBlock(Targets.Attack, blockLevel, blockNum, nowHitPositionRelative);
|
||||
sceneBlockCon.InitializeBlock(environmentObj);
|
||||
targetCon.AttackModeChange(nowHitPositionRelative);
|
||||
ChangeMouseMode(MouseMode.Default);
|
||||
}
|
||||
break;
|
||||
@ -102,7 +97,9 @@ private void Update()
|
||||
else
|
||||
{
|
||||
// if agent or enemy is not nearby, create new block
|
||||
targetCon.PlayTargetChange(Targets.Go, nowHitPositionRelative, blockLevel, blockNum);
|
||||
sceneBlockCon.CreateNewBlock(Targets.Go, blockLevel, blockNum, nowHitPositionRelative);
|
||||
sceneBlockCon.InitializeBlock(environmentObj);
|
||||
targetCon.GotoModeChange(nowHitPositionRelative);
|
||||
ChangeMouseMode(MouseMode.Default);
|
||||
}
|
||||
break;
|
||||
@ -143,7 +140,7 @@ public void ChangeMouseMode(MouseMode mouseMode, int level = -1, int blockNum =
|
||||
// while blockLevel is not set, send error message
|
||||
messageCon.PushMessage(new List<string> { "[ERROR]MouseInMap:ChangeMouseMode:", "Level not set!", "mouseMode=", mouseMode.ToString() },
|
||||
new List<string> { messageCon.errorColor });
|
||||
blockLevel = commonParamCon.scenePrefabSet.GetLevelNumber(nowTargetType);
|
||||
blockLevel = paramCon.scenePrefabSet.GetLevelNumber(nowTargetType);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -155,7 +152,7 @@ public void ChangeMouseMode(MouseMode mouseMode, int level = -1, int blockNum =
|
||||
if (blockNum < 0)
|
||||
{
|
||||
// while blockNum is not set, random choose block type
|
||||
this.blockNum = Random.Range(0, commonParamCon.scenePrefabSet.GetBlockNumber(blockLevel, nowTargetType));
|
||||
this.blockNum = Random.Range(0, paramCon.scenePrefabSet.GetBlockNumber(blockLevel, nowTargetType));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -163,7 +160,7 @@ public void ChangeMouseMode(MouseMode mouseMode, int level = -1, int blockNum =
|
||||
this.blockNum = blockNum;
|
||||
}
|
||||
// set previewModel
|
||||
previewModel = commonParamCon.scenePrefabSet.GetPrefab(blockLevel, this.blockNum, nowTargetType);
|
||||
previewModel = paramCon.scenePrefabSet.GetPrefab(blockLevel, this.blockNum, nowTargetType);
|
||||
mousePreviewCon.ChangePreviewTo(previewModel);
|
||||
break;
|
||||
|
||||
|
@ -4,23 +4,22 @@
|
||||
|
||||
public class PlayerCamera : MonoBehaviour
|
||||
{
|
||||
private float normalSpeed = 0.0035f;
|
||||
private float shiftSpeed = 0.06f;
|
||||
private float zoomSpeed = -10.0f;
|
||||
private float rotateSpeed = 0.1f;
|
||||
public float normalSpeed = 0.0035f;
|
||||
public float shiftSpeed = 0.06f;
|
||||
public float zoomSpeed = -10.0f;
|
||||
public float rotateSpeed = 0.1f;
|
||||
|
||||
private float maxHeight = 40f;
|
||||
private float minHeight = 6f;
|
||||
public float maxHeight = 40f;
|
||||
public float minHeight = 6f;
|
||||
|
||||
private Vector2 startMouseP;
|
||||
private Vector2 dragMouseP;
|
||||
private Vector3 defaultCamPosition;
|
||||
public Vector2 startMouseP;
|
||||
public Vector2 dragMouseP;
|
||||
|
||||
private float speed;
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
defaultCamPosition = transform.position;
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@ -38,12 +37,6 @@ void Update()
|
||||
zoomSpeed = 10.0f;
|
||||
}
|
||||
|
||||
// reset camera position
|
||||
if (Input.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
transform.position = defaultCamPosition;
|
||||
}
|
||||
|
||||
float hsp = transform.position.y * speed * Input.GetAxis("Horizontal"); // horizontal movement speed
|
||||
float vsp = transform.position.y * speed * Input.GetAxis("Vertical"); // vertical movement speed
|
||||
float scrollSp = Mathf.Log(transform.position.y) * -zoomSpeed * Input.GetAxis("Mouse ScrollWheel"); // scroll speed
|
||||
|
@ -1,40 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = (T)FindObjectOfType(typeof(T));
|
||||
if (_instance == null)
|
||||
{
|
||||
Debug.LogError("An instance of " + typeof(T) + " is needed in the scene, but there is none.");
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = this as T;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
// keep this instance through scene change
|
||||
public void KeepThroughSceneChange()
|
||||
{
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a056057ed828e274b954ff7b8b2cb2f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class StartSeneDataremove : MonoBehaviour
|
||||
public class StartSeneData : MonoBehaviour
|
||||
{
|
||||
[Header("Game mode")]
|
||||
public int gameMode = 0;// default trainning mode
|
@ -12,8 +12,8 @@
|
||||
[CreateAssetMenu(menuName = "All Scene Prefab Set")]
|
||||
public class SceneBlocksSet : ScriptableObject
|
||||
{
|
||||
public TargetLevelsSet[] targetLevels = new TargetLevelsSet[2];
|
||||
public Targets[] targets = new Targets[2];
|
||||
public TargetLevelsSet[] targetLevels = new TargetLevelsSet[3];
|
||||
public Targets[] targets = new Targets[3];
|
||||
|
||||
private GameObject hudObj;
|
||||
private MessageBoxController messageBoxController;
|
||||
|
@ -7,10 +7,10 @@
|
||||
|
||||
public class ButtonActivateColorChanger : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private List<Button> clickableButton = new List<Button>();
|
||||
[SerializeField] private List<Button> unclickableButton = new List<Button>();
|
||||
public List<Button> clickableButton = new List<Button>();
|
||||
public List<Button> unclickableButton = new List<Button>();
|
||||
|
||||
[SerializeField] private float colorChangeSpeed = 0.1f;
|
||||
public float colorChangeSpeed = 0.1f;
|
||||
|
||||
public bool clickable = true;
|
||||
|
||||
|
@ -7,17 +7,17 @@
|
||||
|
||||
public class EnvironmentUIControl : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject targetControllerObj;
|
||||
[SerializeField] private GameObject parameterContainerObj;
|
||||
[SerializeField] private GameObject groundCanvasObj;
|
||||
[SerializeField] private GameObject chartObj;
|
||||
[SerializeField] private GameObject HUDObj;
|
||||
[SerializeField] private TextMeshProUGUI remainTimeText;
|
||||
[SerializeField] private TextMeshProUGUI targetTypeText;
|
||||
[SerializeField] private TextMeshProUGUI winLoseText;
|
||||
[SerializeField] private TextMeshProUGUI stateText;
|
||||
[SerializeField] private float resultTimeout = 1f;
|
||||
[SerializeField] private GameObject gaugeImgObj;
|
||||
public GameObject targetControllerObj;
|
||||
public GameObject parameterContainerObj;
|
||||
public GameObject groundCanvasObj;
|
||||
public GameObject chartObj;
|
||||
public GameObject HUDObj;
|
||||
public TextMeshProUGUI remainTimeText;
|
||||
public TextMeshProUGUI targetTypeText;
|
||||
public TextMeshProUGUI winLoseText;
|
||||
public TextMeshProUGUI stateText;
|
||||
public float resultTimeout = 1f;
|
||||
public GameObject gaugeImgObj;
|
||||
|
||||
private StringBuilder stateBuilder = new StringBuilder();
|
||||
private LineChart realTimeRewardChart = null;
|
||||
@ -131,31 +131,31 @@ public void UpdateTargetGauge(float firebasesBelong, float belongMaxPoint)
|
||||
}
|
||||
|
||||
// update targetType text
|
||||
public void UpdateTargetType(Targets targetInt)
|
||||
public void UpdateTargetType(int targetInt)
|
||||
{
|
||||
switch (targetInt)
|
||||
{
|
||||
case Targets.Go:
|
||||
case (int)Targets.Go:
|
||||
targetTypeText.text = "GOTO";
|
||||
targetTypeText.color = Color.blue;
|
||||
break;
|
||||
|
||||
case Targets.Attack:
|
||||
case (int)Targets.Attack:
|
||||
targetTypeText.text = "Attack!";
|
||||
targetTypeText.color = Color.red;
|
||||
break;
|
||||
|
||||
case Targets.Defence:
|
||||
case (int)Targets.Defence:
|
||||
targetTypeText.text = "Defence";
|
||||
targetTypeText.color = Color.green;
|
||||
break;
|
||||
|
||||
case Targets.Free:
|
||||
case (int)Targets.Free:
|
||||
targetTypeText.text = "Free";
|
||||
targetTypeText.color = Color.yellow;
|
||||
break;
|
||||
|
||||
case Targets.Stay:
|
||||
case (int)Targets.Stay:
|
||||
targetTypeText.text = "Stay";
|
||||
targetTypeText.color = Color.white;
|
||||
break;
|
||||
@ -169,10 +169,10 @@ public void UpdateTargetType(Targets targetInt)
|
||||
|
||||
// update state text
|
||||
// public TextMeshProUGUI stateText;
|
||||
// targetState[0] = targetType;
|
||||
// targetState[1] = targetEndPosition.x / raySensors.viewDistance; // normalization
|
||||
// targetState[2] = targetEndPosition.y / raySensors.viewDistance;
|
||||
// targetState[3] = targetEndPosition.z / raySensors.viewDistance;
|
||||
// targetState[0] = targetTypeInt;
|
||||
// targetState[1] = targetPosition.x / raySensors.viewDistance; // normalization
|
||||
// targetState[2] = targetPosition.y / raySensors.viewDistance;
|
||||
// targetState[3] = targetPosition.z / raySensors.viewDistance;
|
||||
// targetState[4] = blockCont.thisBlock.firebasesAreaDiameter / raySensors.viewDistance;
|
||||
// targetState[5] = blockCont.thisBlock.belongRatio;
|
||||
// float[] myObserve = { transform.localPosition.x/raySensors.viewDistance, transform.localPosition.y / raySensors.viewDistance, transform.localPosition.z / raySensors.viewDistance, transform.eulerAngles.y/360f }
|
||||
@ -190,6 +190,8 @@ public void UpdateStateText(float[] targetStates, float inAreaState, float remai
|
||||
stateBuilder.Append(targetStates[3]);
|
||||
stateBuilder.Append("\r\nTargetDiameter:");
|
||||
stateBuilder.Append(targetStates[4]);
|
||||
stateBuilder.Append("\r\nTargetBelongRatio:");
|
||||
stateBuilder.Append(targetStates[5]);
|
||||
stateBuilder.Append("\r\nInArea:");
|
||||
stateBuilder.Append(inAreaState);
|
||||
stateBuilder.Append("\r\nRemainTime:");
|
||||
@ -197,10 +199,9 @@ public void UpdateStateText(float[] targetStates, float inAreaState, float remai
|
||||
stateBuilder.Append("\r\nGunReady:");
|
||||
stateBuilder.Append(gunReadyToggle);
|
||||
stateBuilder.Append("\r\nMyPosition:");
|
||||
stateBuilder.Append(myObserve[0]+"_").Append(myObserve[1]+"_").Append(myObserve[2]);
|
||||
stateBuilder.Append(myObserve[0]).Append(myObserve[1]).Append(myObserve[2]);
|
||||
stateBuilder.Append("\r\nMyRotation:");
|
||||
stateBuilder.Append(myObserve[3]+"_").Append(myObserve[4]);
|
||||
|
||||
stateBuilder.Append(myObserve[3]);
|
||||
|
||||
stateText.text = stateBuilder.ToString();
|
||||
}
|
||||
|
@ -7,11 +7,11 @@
|
||||
public class HUDController : MonoBehaviour
|
||||
{
|
||||
public bool chartOn = false;
|
||||
[SerializeField] private GameObject sideChannelObj;
|
||||
[SerializeField] private Toggle chartOnToggleObj;
|
||||
[SerializeField] private Button saveModelButton;
|
||||
[SerializeField] private TMP_InputField chartOnTimeOutInputObj;
|
||||
[SerializeField] private TMP_InputField enemyNumInputObj;
|
||||
public GameObject sideChannelObj;
|
||||
public Toggle chartOnToggleObj;
|
||||
public Button saveModelButton;
|
||||
public TMP_InputField chartOnTimeOutInputObj;
|
||||
public TMP_InputField enemyNumInputObj;
|
||||
public float chartOnTimeOut = 1;
|
||||
public int enemyNum = 3;
|
||||
public float chartOnTimeOutDefault = 120f;
|
||||
@ -44,6 +44,18 @@ public void OnChartOnToggleChange()
|
||||
chartOn = chartOnToggleObj.isOn;
|
||||
}
|
||||
|
||||
public void OnEnemyNumTextChange()
|
||||
{
|
||||
try
|
||||
{
|
||||
enemyNum = Math.Abs(int.Parse(enemyNumInputObj.GetComponent<TMP_InputField>().text));
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
enemyNum = 3;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnChartTimeOutTextChange()
|
||||
{
|
||||
try
|
||||
|
@ -6,7 +6,7 @@
|
||||
public class LevelButton : MonoBehaviour
|
||||
{
|
||||
public int level;
|
||||
[SerializeField] private TextMeshProUGUI levelText;
|
||||
public TextMeshProUGUI levelText;
|
||||
public void Initialization(int level)
|
||||
{
|
||||
this.level = level;
|
||||
|
@ -8,9 +8,9 @@ public class LevelPanel : MonoBehaviour
|
||||
{
|
||||
private int levelNum = 0;
|
||||
private float buttonHeight = 30;
|
||||
[SerializeField] private TargetUIController.PrimaryButtonType primaryButtonType;
|
||||
[SerializeField] private GameObject levelButtonPrefab;
|
||||
[SerializeField] private GameObject hudObj;
|
||||
public TargetUIController.PrimaryButtonType primaryButtonType;
|
||||
public GameObject levelButtonPrefab;
|
||||
public GameObject hudObj;
|
||||
private TargetUIController targetUIController;
|
||||
public Vector2 defaultPosition = Vector2.zero;
|
||||
public Vector2 targetPosition = Vector2.zero;
|
||||
|
@ -1,23 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class LevelProbabilityPanel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject singleTargetLevelProbabilityPanel;
|
||||
[SerializeField] private GameObject startSceneData;
|
||||
private SceneBlocksSet scenePrefabSet;
|
||||
|
||||
public List<TargetLevelProbabilityPanel> targetLevelProbabilityPanel = new List<TargetLevelProbabilityPanel>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
scenePrefabSet = CommonParameterContainer.Instance.scenePrefabSet;
|
||||
for (int i = 0; i < scenePrefabSet.targetLevels.Length; i++)
|
||||
{
|
||||
Targets nowTarget = scenePrefabSet.targets[i];
|
||||
targetLevelProbabilityPanel.Add(Instantiate(singleTargetLevelProbabilityPanel, transform).GetComponent<TargetLevelProbabilityPanel>());
|
||||
targetLevelProbabilityPanel[i].IntializePanels(nowTarget, nowTarget.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44d064c42ee56374e94671f4f9f9d650
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -9,10 +9,11 @@ public class MessageBoxController : MonoBehaviour
|
||||
public string warningColor = "#ffa500ff";
|
||||
public string errorColor = "#800000ff";
|
||||
public string goodColor = "#00ff00ff";
|
||||
[SerializeField] private GameObject messagePanelObj;
|
||||
[SerializeField] private GameObject messageTextPrefab;
|
||||
public GameObject messagePanelObj;
|
||||
public GameObject messageTextPrefab;
|
||||
|
||||
[SerializeField] private List<Message> messages = new List<Message>();
|
||||
[SerializeField]
|
||||
private List<Message> messages = new List<Message>();
|
||||
|
||||
/// <summary>
|
||||
/// Pushes a simple message to the message list.
|
||||
@ -44,7 +45,7 @@ public void PushMessage(string text)
|
||||
/// This method pushes multi-color text messages to the message list and handles message overflow to ensure that the message list does not grow indefinitely.
|
||||
/// If the lengths of the message text list and the color list do not match, it either removes excess colors or adds white color to the extra messages.
|
||||
/// </remarks>
|
||||
public void PushMessage(List<string> messageList, List<string> colorList)
|
||||
public void PushMessage(List<string> messageList,List<string> colorList)
|
||||
{
|
||||
// check messages and colors list length match
|
||||
if (messageList.Count != colorList.Count)
|
||||
@ -52,7 +53,7 @@ public void PushMessage(List<string> messageList, List<string> colorList)
|
||||
// delete extra colors or add white color to extra messages
|
||||
if (messageList.Count > colorList.Count)
|
||||
{
|
||||
while (messageList.Count > colorList.Count)
|
||||
while(messageList.Count > colorList.Count)
|
||||
{
|
||||
colorList.Add(defaultColor);
|
||||
}
|
||||
@ -61,6 +62,7 @@ public void PushMessage(List<string> messageList, List<string> colorList)
|
||||
{
|
||||
colorList.RemoveRange(messageList.Count, colorList.Count - messageList.Count);
|
||||
}
|
||||
|
||||
}
|
||||
MessageOverflowHandler();
|
||||
Message newMessage = new Message();
|
||||
|
@ -5,11 +5,11 @@
|
||||
|
||||
public class SingleLevelProbabilityPanel : MonoBehaviour
|
||||
{
|
||||
public TextMeshProUGUI levelNameText;
|
||||
public TMP_InputField inputField;
|
||||
[SerializeField] private TextMeshProUGUI levelNameText;
|
||||
[SerializeField] private Button lockButton;
|
||||
[SerializeField] private Image lockImg;
|
||||
[SerializeField] private Image unlockImg;
|
||||
public Button lockButton;
|
||||
public Image lockImg;
|
||||
public Image unlockImg;
|
||||
|
||||
public Slider probabilitySlider;
|
||||
|
||||
|
@ -3,23 +3,22 @@
|
||||
|
||||
public class StartMenuAnimations : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject maskObj;
|
||||
[SerializeField] private GameObject mixButton;
|
||||
[SerializeField] private GameObject attackButton;
|
||||
[SerializeField] private GameObject gotoButton;
|
||||
[SerializeField] private GameObject freeButton;
|
||||
public GameObject maskObj;
|
||||
public GameObject mixButton;
|
||||
public GameObject attackButton;
|
||||
public GameObject gotoButton;
|
||||
public GameObject freeButton;
|
||||
|
||||
[Header("Animation Parameter")]
|
||||
[SerializeField] private float animeDuration = 0.2f;
|
||||
public float animeDuration = 0.2f;
|
||||
|
||||
[SerializeField] private float animeMoveXDistance = 20f;
|
||||
[SerializeField] private float animeMoveYDistance = 20f;
|
||||
public float animeMoveXDistance = 20f;
|
||||
public float animeMoveYDistance = 20f;
|
||||
|
||||
[SerializeField] private float animeScaleX = 1.2f;
|
||||
[SerializeField] private float animeScaleY = 1.2f;
|
||||
public float animeScaleX = 1.2f;
|
||||
public float animeScaleY = 1.2f;
|
||||
|
||||
[SerializeField] private float maskScaleX = 1;
|
||||
[SerializeField] private float maskScaleY = 0.4f;
|
||||
public float maskScaleX = 1;
|
||||
public float maskScaleY = 0.4f;
|
||||
|
||||
private Vector3 mixOriginDestination;
|
||||
private Vector3 attackOriginDestination;
|
||||
@ -110,6 +109,8 @@ private void MaximizeMaskObj()
|
||||
private Vector3 fixCanvas(Vector3 vector)
|
||||
{
|
||||
// fix position of button while canvas is changed
|
||||
return vector.FixCanvas(originalCanvas, transform.parent.position);
|
||||
Vector3 fixedV = vector;
|
||||
fixedV += (transform.parent.position - originalCanvas);
|
||||
return fixedV;
|
||||
}
|
||||
}
|
@ -3,20 +3,20 @@
|
||||
|
||||
public class StartMenuProbabilityPanel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject singleTargetLevelProbabilityPanel;
|
||||
[SerializeField] private GameObject startSceneData;
|
||||
public GameObject singleTargetLevelProbabilityPanel;
|
||||
public GameObject startSceneData;
|
||||
private SceneBlocksSet scenePrefabSet;
|
||||
|
||||
public List<TargetLevelProbabilityPanel> targetLevelProbabilityPanel = new List<TargetLevelProbabilityPanel>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
scenePrefabSet = CommonParameterContainer.Instance.scenePrefabSet;
|
||||
scenePrefabSet = startSceneData.GetComponent<StartSeneData>().scenePrefabSet;
|
||||
for (int i = 0; i < scenePrefabSet.targetLevels.Length; i++)
|
||||
{
|
||||
Targets nowTarget = scenePrefabSet.targets[i];
|
||||
targetLevelProbabilityPanel.Add(Instantiate(singleTargetLevelProbabilityPanel, transform).GetComponent<TargetLevelProbabilityPanel>());
|
||||
targetLevelProbabilityPanel[i].IntializePanels(nowTarget, nowTarget.ToString());
|
||||
targetLevelProbabilityPanel[i].IntializePanels(scenePrefabSet.GetLevelNumber(nowTarget), nowTarget.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -5,25 +5,26 @@
|
||||
|
||||
public class StartUIManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private int waitTimeLimit = 45;
|
||||
[SerializeField] private GameObject sceneLoaderObj;
|
||||
[SerializeField] private GameObject targetLevelProbabilityPanelOBJ;
|
||||
[SerializeField] private TextMeshProUGUI messageTextObj;
|
||||
[SerializeField] private TextMeshProUGUI waitTimeTextObj;
|
||||
public int waitTimeLimit = 45;
|
||||
public GameObject sceneLoaderObj;
|
||||
public GameObject startSceneDataObj;
|
||||
public GameObject targetLevelProbabilityPanelOBJ;
|
||||
public TextMeshProUGUI messageTextObj;
|
||||
public TextMeshProUGUI waitTimeTextObj;
|
||||
|
||||
private SceneLoader sceneLoader;
|
||||
private StartSeneData startSceneData;
|
||||
private ButtonActivateColorChanger buttonActivateColorChanger;
|
||||
private LevelProbabilityPanel startMenuProbabilityPanel;
|
||||
private CommonParameterContainer commonParameterContainer;
|
||||
private StartMenuProbabilityPanel startMenuProbabilityPanel;
|
||||
private float startTime;
|
||||
private float nowTime;
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
sceneLoader = sceneLoaderObj.GetComponent<SceneLoader>();
|
||||
startSceneData = startSceneDataObj.GetComponent<StartSeneData>();
|
||||
buttonActivateColorChanger = GetComponent<ButtonActivateColorChanger>();
|
||||
startMenuProbabilityPanel = targetLevelProbabilityPanelOBJ.GetComponent<LevelProbabilityPanel>();
|
||||
commonParameterContainer = CommonParameterContainer.Instance;
|
||||
startMenuProbabilityPanel = targetLevelProbabilityPanelOBJ.GetComponent<StartMenuProbabilityPanel>();
|
||||
messageTextObj.text = "";
|
||||
buttonActivateColorChanger.InitializeAllButtonColor();
|
||||
}
|
||||
@ -35,19 +36,15 @@ private void Update()
|
||||
waitTimeTextObj.text = ((int)Math.Round(leftTime)).ToString();
|
||||
if (leftTime <= 1)
|
||||
{
|
||||
// if time limit is over, end game
|
||||
# if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.isPlaying = false;
|
||||
#else
|
||||
StopGame();
|
||||
#endif
|
||||
// if time limit is over, load Train Scene
|
||||
sceneLoader.LoadGameScene(SceneLoader.SceneType.Train);
|
||||
}
|
||||
}
|
||||
|
||||
// while StartButton-Play Pressed
|
||||
public void OnPlayButtonPressed()
|
||||
{
|
||||
commonParameterContainer.gameMode = 1;
|
||||
startSceneData.gameMode = 1;
|
||||
sceneLoader.LoadGameScene(SceneLoader.SceneType.Play);
|
||||
messageTextObj.text = "Loading Play Scene...";
|
||||
}
|
||||
@ -55,30 +52,30 @@ public void OnPlayButtonPressed()
|
||||
public void OnAttackTrainButtonPressed()
|
||||
{
|
||||
// while Train-Attack-Button Pressed
|
||||
commonParameterContainer.attackProb = 1f;
|
||||
startSceneData.attackProb = 1f;
|
||||
ApplicateProbabilityToData();
|
||||
LoadTrainScene();
|
||||
}
|
||||
public void OnGotoTrainButtonPressed()
|
||||
{
|
||||
// while Train-Goto-Button Pressed
|
||||
commonParameterContainer.gotoProb = 1f;
|
||||
startSceneData.gotoProb = 1f;
|
||||
ApplicateProbabilityToData();
|
||||
LoadTrainScene();
|
||||
}
|
||||
public void OnFreeTrainButtonPressed()
|
||||
{
|
||||
// while Train-Free-Button Pressed
|
||||
commonParameterContainer.attackProb = 0f;
|
||||
commonParameterContainer.gotoProb = 0f;
|
||||
commonParameterContainer.defenceProb = 0f;
|
||||
startSceneData.attackProb = 0f;
|
||||
startSceneData.gotoProb = 0f;
|
||||
startSceneData.defenceProb = 0f;
|
||||
LoadTrainScene();
|
||||
}
|
||||
public void OnMixTrainButtonPressed()
|
||||
{
|
||||
// while Train-Mix-Button Pressed
|
||||
commonParameterContainer.attackProb = 0.333f;
|
||||
commonParameterContainer.gotoProb = 0.333f;
|
||||
startSceneData.attackProb = 0.333f;
|
||||
startSceneData.gotoProb = 0.333f;
|
||||
LoadTrainScene();
|
||||
}
|
||||
private void LoadTrainScene()
|
||||
@ -90,20 +87,13 @@ private void LoadTrainScene()
|
||||
|
||||
private void ApplicateProbabilityToData()
|
||||
{
|
||||
for(int targetIndex = 0;targetIndex < commonParameterContainer.scenePrefabSet.targetLevels.Length; targetIndex++)
|
||||
for (int i = 0; i < startSceneData.scenePrefabSet.targetLevels[0].levelSize; i++)
|
||||
{
|
||||
Targets nowTarget = commonParameterContainer.scenePrefabSet.targets[targetIndex];
|
||||
for(int levelIndex = 0; levelIndex < commonParameterContainer.scenePrefabSet.targetLevels[targetIndex].levelSize; levelIndex++)
|
||||
{
|
||||
commonParameterContainer.levelProbs[nowTarget] = startMenuProbabilityPanel.targetLevelProbabilityPanel[targetIndex].GetTargetProb();
|
||||
}
|
||||
startSceneData.gotoLevelProbs.Add(startMenuProbabilityPanel.targetLevelProbabilityPanel[0].singleLevelPanels[i].ProbabilityValue);
|
||||
}
|
||||
for(int i = 0; i < startSceneData.scenePrefabSet.targetLevels[1].levelSize; i++)
|
||||
{
|
||||
startSceneData.attackLevelProbs.Add(startMenuProbabilityPanel.targetLevelProbabilityPanel[1].singleLevelPanels[i].ProbabilityValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void StopGame()
|
||||
{
|
||||
// stop game,end program
|
||||
Debug.Log("Game End");
|
||||
Application.Quit();
|
||||
}
|
||||
}
|
@ -3,36 +3,27 @@
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class TargetLevelProbabilityPanel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject singleLevelProbabilityPanel;
|
||||
[SerializeField] private GameObject targetTitleText;
|
||||
public GameObject singleLevelProbabilityPanel;
|
||||
public GameObject targetTitleText;
|
||||
|
||||
private GameObject titleText;
|
||||
public List<GameObject> singleLevelPanelsObjs = new List<GameObject>();
|
||||
public List<SingleLevelProbabilityPanel> singleLevelPanels = new List<SingleLevelProbabilityPanel>();
|
||||
|
||||
private int panelNum = 0;
|
||||
private Targets thisTarget;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes panels for a specific target, including the title and level probabilities.
|
||||
/// </summary>
|
||||
/// <param name="thisTarget">The specified target, used to obtain associated level numbers and probability data.</param>
|
||||
/// <param name="titleName">The title name for the panel.</param>
|
||||
/// <remarks>
|
||||
/// This method first calculates the panel dimensions, then creates and sets the title text. Subsequently, it creates individual probability panels for each level and adds event listeners for sliders and input fields.
|
||||
/// It relies on the CommonParameterContainer instance to access scene prefab sets and level probabilities.
|
||||
/// </remarks>
|
||||
public void IntializePanels(Targets thisTarget, string titleName)
|
||||
public void IntializePanels(int levelNum, string titleName)
|
||||
{
|
||||
this.thisTarget = thisTarget;
|
||||
int levelNum = CommonParameterContainer.Instance.scenePrefabSet.GetLevelNumber(thisTarget);
|
||||
// initialize target level probability panel size
|
||||
float defaultWidth = singleLevelProbabilityPanel.GetComponent<RectTransform>().sizeDelta.x;
|
||||
float defaultLevelHeight = singleLevelProbabilityPanel.GetComponent<RectTransform>().sizeDelta.y;
|
||||
float titleHeight = targetTitleText.GetComponent<RectTransform>().sizeDelta.y;
|
||||
float averageProbability = 1f / levelNum;
|
||||
float lastLevelProbability = 1f - averageProbability * (levelNum - 1);
|
||||
// Debug.Log("averageProbability: " + averageProbability);
|
||||
transform.GetComponent<RectTransform>().sizeDelta = new Vector2(defaultWidth, (defaultLevelHeight * levelNum) + titleHeight);
|
||||
// create title text
|
||||
@ -44,8 +35,7 @@ public void IntializePanels(Targets thisTarget, string titleName)
|
||||
int tempIndex = i;
|
||||
singleLevelPanelsObjs.Add(Instantiate(singleLevelProbabilityPanel, transform));
|
||||
singleLevelPanels.Add(singleLevelPanelsObjs[i].GetComponent<SingleLevelProbabilityPanel>());
|
||||
Debug.Log(CommonParameterContainer.Instance.levelProbs.Count);
|
||||
singleLevelPanels[i].InitializeLevelProbabilityPanel(i, CommonParameterContainer.Instance.levelProbs[thisTarget][i]);
|
||||
singleLevelPanels[i].InitializeLevelProbabilityPanel(i, i == levelNum - 1 ? lastLevelProbability : averageProbability);
|
||||
//add onValueChanged event to slider and input field
|
||||
singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnProbabilityValueChange(value, tempIndex));
|
||||
singleLevelPanels[i].inputField.onEndEdit.AddListener((value) => OnProbabilityValueChange(value, tempIndex));
|
||||
@ -54,21 +44,22 @@ public void IntializePanels(Targets thisTarget, string titleName)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the probability values for all levels of the current target.
|
||||
/// Adds an event trigger entry to an event trigger.
|
||||
/// </summary>
|
||||
/// <returns>A list of floating-point numbers containing the probability values for each level.</returns>
|
||||
/// <remarks>
|
||||
/// This method iterates through the panels of all levels, collecting and returning the probability value for each level.
|
||||
/// It relies on the singleLevelPanels list, which should have been properly initialized and populated before calling this method.
|
||||
/// </remarks>
|
||||
public List<float> GetTargetProb()
|
||||
/// <param name="trigger">The event trigger object.</param>
|
||||
/// <param name="type">The event trigger type.</param>
|
||||
/// <param name="action">The event handler method to execute.</param>
|
||||
private void AddEventTrigger(GameObject gameObject, EventTriggerType triggerType, System.Action<BaseEventData> action)
|
||||
{
|
||||
List<float> targetProb = new List<float>();
|
||||
for (int i = 0; i < panelNum; i++)
|
||||
EventTrigger eventTrigger = gameObject.GetComponent<EventTrigger>();
|
||||
if (eventTrigger == null)
|
||||
{
|
||||
targetProb.Add(singleLevelPanels[i].ProbabilityValue);
|
||||
eventTrigger = gameObject.AddComponent<EventTrigger>();
|
||||
}
|
||||
return targetProb;
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = triggerType;
|
||||
entry.callback.AddListener(new UnityEngine.Events.UnityAction<BaseEventData>(action));
|
||||
eventTrigger.triggers.Add(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -84,20 +75,17 @@ private void OnProbabilityValueChange<T>(T value, int exceptedIndex)
|
||||
case float floatValue:
|
||||
changedValue = floatValue;
|
||||
break;
|
||||
|
||||
case string stringValue:
|
||||
changedValue = float.Parse(stringValue);
|
||||
// limit the value between 0 and 1
|
||||
if (changedValue > 1 && changedValue <= 100)
|
||||
if(changedValue>1 && changedValue <=100)
|
||||
{
|
||||
changedValue /= 100;
|
||||
}
|
||||
else if (changedValue > 100)
|
||||
}else if(changedValue>100)
|
||||
{
|
||||
changedValue = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.LogError("Invalid value type!");
|
||||
throw new ArgumentException("Unsupported value type");
|
||||
@ -176,19 +164,8 @@ private void enableSliderListener()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recalculates correction values.
|
||||
/// calculate the correction value to each panel,while the total value is not equal to 1
|
||||
/// </summary>
|
||||
/// <param name="correctionValues">The current array of correction values.</param>
|
||||
/// <param name="exceptedIndex">The index of the panel that is expected not to change.</param>
|
||||
/// <param name="value">The expected probability value.</param>
|
||||
/// <param name="extraValue">Additional correction value.</param>
|
||||
/// <param name="maxLimitValue">The maximum limit for the probability value.</param>
|
||||
/// <returns>Returns a tuple containing a float array and an integer.
|
||||
/// The float array is the new correction values, and the integer is the number of panels that need to be corrected in the next iteration.</returns>
|
||||
/// <remarks>
|
||||
/// This method calculates new correction values based on the provided parameters.
|
||||
/// During the iteration, some panels might exceed set limits, and their values will need to be corrected in the next iteration.
|
||||
/// </remarks>
|
||||
private (float[], int) reCalculateCorrectionValues(float[] correctionValues, int exceptedIndex, float value, float extraValue, float maxLimitValue)
|
||||
{
|
||||
// the number of panels which need to be corrected in next iteration
|
||||
@ -272,20 +249,20 @@ private void enableSliderListener()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies correction values to adjust the probability values for each level of the current target.
|
||||
/// applicate correction value to each panel
|
||||
/// </summary>
|
||||
/// <param name="correctionValues">An array of correction values to be applied to the probability value of each level.</param>
|
||||
/// <remarks>
|
||||
/// This method iterates through all the level panels, updating the probability by subtracting the corresponding correction value from the probability value of each level.
|
||||
/// It also synchronously updates the level probabilities for this target stored in the CommonParameterContainer instance.
|
||||
/// This method assumes that the length of the correctionValues array matches the number of level panels.
|
||||
/// </remarks>
|
||||
private void applyCorrectionValue(float[] correctionValues)
|
||||
{
|
||||
for (int i = 0; i < panelNum; i++)
|
||||
{
|
||||
/* if (singleLevelPanels[i].ProbabilityValue - correctionValues[i] < 0)
|
||||
{
|
||||
Debug.LogWarning("Probability value is less than 0");
|
||||
Debug.Log(i);
|
||||
Debug.Log(singleLevelPanels[i].ProbabilityValue);
|
||||
Debug.Log(correctionValues[i]);
|
||||
}*/
|
||||
singleLevelPanels[i].SetProbability(singleLevelPanels[i].ProbabilityValue - correctionValues[i]);
|
||||
CommonParameterContainer.Instance.levelProbs[thisTarget][i] = singleLevelPanels[i].ProbabilityValue;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
@ -7,27 +8,27 @@ public class TargetUIController : MonoBehaviour
|
||||
{
|
||||
// Controller to control the UI of the target,
|
||||
// select target type, select prefeb to set or sth.
|
||||
public GameObject targetControllerObj;
|
||||
|
||||
[SerializeField] private GameObject targetControllerObj;
|
||||
[SerializeField] private GameObject mouseSelectorObj;
|
||||
[SerializeField] private GameObject environmentUIObj;
|
||||
public GameObject mouseSelectorObj;
|
||||
public GameObject environmentUIObj;
|
||||
|
||||
[SerializeField] private float levelButtonHeight = 30;
|
||||
public float levelButtonHeight = 30;
|
||||
|
||||
[Header("PrimaryButton")]
|
||||
[SerializeField] private Button clearGameButton;
|
||||
|
||||
[SerializeField] private Button setEnemyButton;
|
||||
[SerializeField] private Button setAttackButton;
|
||||
[SerializeField] private Button setGotoButton;
|
||||
[SerializeField] private Button setFreeButton;
|
||||
[SerializeField] private Button setStayButton;
|
||||
public Button clearGameButton;
|
||||
public Button setEnemyButton;
|
||||
public Button setAttackButton;
|
||||
public Button setGotoButton;
|
||||
public Button setFreeButton;
|
||||
public Button setStayButton;
|
||||
public int primaryButtonNumber = 6;
|
||||
|
||||
[Header("LevelPanel")]
|
||||
[SerializeField] private GameObject gotoLevelPanel;
|
||||
public GameObject gotoLevelPanel;
|
||||
|
||||
[SerializeField] private GameObject attackLevelPanel;
|
||||
[SerializeField] private float levelPanelAnimeTime = 0.2f;
|
||||
public GameObject attackLevelPanel;
|
||||
public float levelPanelAnimeTime = 0.2f;
|
||||
|
||||
private MouseInMap mouseInMapCon;
|
||||
private EnvironmentUIControl envUICon;
|
||||
@ -91,7 +92,7 @@ public void LevelButtonPressed(PrimaryButtonType primaryButtonType, int level =
|
||||
public void ClearGamePressed()
|
||||
{
|
||||
// Clear all enemies and targets. set gamemode to Stay mode
|
||||
targetCon.PlayTargetChange(Targets.Stay);
|
||||
targetCon.StayModeChange();
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
|
||||
// disable setStayButton and enable other buttons
|
||||
buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
|
||||
@ -100,14 +101,14 @@ public void ClearGamePressed()
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, false);
|
||||
targetCon.PlayModeInitialize();
|
||||
targetCon.PlayInitialize();
|
||||
}
|
||||
|
||||
// Set Free Button Pressed, change Target mode to free mode
|
||||
public void SetFreePressed()
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
|
||||
targetCon.PlayTargetChange(Targets.Free);
|
||||
targetCon.FreeModeChange();
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
@ -118,7 +119,7 @@ public void SetFreePressed()
|
||||
public void SetStayPressed()
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
|
||||
targetCon.PlayTargetChange(Targets.Stay);
|
||||
targetCon.StayModeChange();
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, false);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
@ -161,9 +162,9 @@ private void SetAttackPressed(int level)
|
||||
/// <param name="levelPanel">The level panel object containing the level buttons.</param>
|
||||
private void AddLevelButtonToColorChanger(GameObject levelPanel)
|
||||
{
|
||||
foreach (Button btn in levelPanel.GetComponent<LevelPanel>().LevelButtonList)
|
||||
foreach(Button btn in levelPanel.GetComponent<LevelPanel>().LevelButtonList)
|
||||
{
|
||||
buttonColorChanger.AddButtonToColorChangerButtonList(btn, true);
|
||||
buttonColorChanger.AddButtonToColorChangerButtonList(btn,true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
public class WorldUIController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private LineChart winChart;
|
||||
public LineChart winChart;
|
||||
public int[] totalGames;
|
||||
public int[] winGames;
|
||||
|
||||
@ -26,33 +26,32 @@ private void Start()
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateChart(Targets targetType, int endType)
|
||||
public void UpdateChart(int targetType, int endType)
|
||||
{
|
||||
float winRatio = 0f;
|
||||
int targetTypeInt = (int)targetType;
|
||||
switch (endType)
|
||||
{
|
||||
case (int)TargetController.EndType.Win:
|
||||
//Win
|
||||
totalGames[targetTypeInt] += 1;
|
||||
winGames[targetTypeInt] += 1;
|
||||
winRatio = (float)winGames[targetTypeInt] / totalGames[targetTypeInt];
|
||||
winChart.AddData(targetTypeInt, winRatio);
|
||||
if (totalGames[targetTypeInt] > maxXAxis)
|
||||
totalGames[targetType] += 1;
|
||||
winGames[targetType] += 1;
|
||||
winRatio = (float)winGames[targetType] / totalGames[targetType];
|
||||
winChart.AddData(targetType, winRatio);
|
||||
if (totalGames[targetType] > maxXAxis)
|
||||
{
|
||||
maxXAxis = totalGames[targetTypeInt];
|
||||
maxXAxis = totalGames[targetType];
|
||||
winChart.AddXAxisData(Convert.ToString(maxXAxis));
|
||||
}
|
||||
break;
|
||||
|
||||
case (int)TargetController.EndType.Lose:
|
||||
//lose
|
||||
totalGames[targetTypeInt] += 1;
|
||||
winRatio = (float)winGames[targetTypeInt] / totalGames[targetTypeInt];
|
||||
winChart.AddData(targetTypeInt, winRatio);
|
||||
if (totalGames[targetTypeInt] > maxXAxis)
|
||||
totalGames[targetType] += 1;
|
||||
winRatio = (float)winGames[targetType] / totalGames[targetType];
|
||||
winChart.AddData(targetType, winRatio);
|
||||
if (totalGames[targetType] > maxXAxis)
|
||||
{
|
||||
maxXAxis = totalGames[targetTypeInt];
|
||||
maxXAxis = totalGames[targetType];
|
||||
winChart.AddXAxisData(Convert.ToString(maxXAxis));
|
||||
}
|
||||
break;
|
||||
|
@ -1,151 +0,0 @@
|
||||
using DG.Tweening; // Importing the DOTween library for smooth animations.
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems; // Using the EventSystem to handle UI interactions.
|
||||
|
||||
public class UIVisibilityController : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private GameObject targetUIObj;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject triggerUIObj;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject canvasObj;
|
||||
|
||||
[SerializeField]
|
||||
private Vector3 slideDirection = Vector3.zero;
|
||||
|
||||
[SerializeField]
|
||||
private Vector3 slideDistance = Vector3.zero;
|
||||
|
||||
[SerializeField]
|
||||
private float slideDuration = 0.2f;
|
||||
|
||||
// Cached positions and states for logic and animation.
|
||||
private Vector3 targetOriginalPosition;
|
||||
|
||||
private Vector3 triggerOriginalPosition;
|
||||
private Vector3 targetEndPosition;
|
||||
private Vector3 triggerEndPosition;
|
||||
private Vector3 originalCanvasPosition;
|
||||
private bool isInActive = true; // Indicates if the UI is currently inactive.
|
||||
private bool isOutActive = false; // Indicates if the UI is currently active.
|
||||
private bool isMouseInTarget = false; // Is the mouse currently over the target UI?
|
||||
private bool isMouseInTrigger = false; // Is the mouse currently over the trigger UI?
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Initial setup of component's states and values.
|
||||
InitializeCanvasPosition();
|
||||
InitializeSlideValues();
|
||||
InitializeEventTrigger();
|
||||
}
|
||||
|
||||
private void InitializeCanvasPosition()
|
||||
{
|
||||
if (canvasObj == null)
|
||||
{
|
||||
// Set canvasObj to the parent if not assigned.
|
||||
canvasObj = transform.parent.gameObject;
|
||||
}
|
||||
originalCanvasPosition = canvasObj.transform.position;
|
||||
}
|
||||
|
||||
private void InitializeSlideValues()
|
||||
{
|
||||
if (slideDirection == Vector3.zero)
|
||||
{
|
||||
// default slide direction is up (set to right).
|
||||
slideDirection = Vector3.right;
|
||||
Debug.LogError("SliderDirection not set, set default right");
|
||||
}
|
||||
if (slideDistance == Vector3.zero)
|
||||
{
|
||||
// default slide distance is based on targetUIObj dimensions.
|
||||
RectTransform targetRT = targetUIObj.GetComponent<RectTransform>();
|
||||
slideDistance = new Vector3(targetRT.rect.width, targetRT.rect.height, 0);
|
||||
}
|
||||
// Determine the start and end positions for sliding.
|
||||
targetOriginalPosition = targetUIObj.transform.position;
|
||||
triggerOriginalPosition = triggerUIObj.transform.position;
|
||||
targetEndPosition = targetOriginalPosition + Vector3.Scale(slideDirection, slideDistance);
|
||||
triggerEndPosition = triggerOriginalPosition + Vector3.Scale(slideDirection, slideDistance);
|
||||
}
|
||||
|
||||
private void InitializeEventTrigger()
|
||||
{
|
||||
// Setting up event triggers for mouse interactions.
|
||||
EventTrigger triggerObjET = triggerUIObj.GetComponent<EventTrigger>();
|
||||
if (triggerObjET == null)
|
||||
{
|
||||
triggerObjET = triggerUIObj.AddComponent<EventTrigger>();
|
||||
}
|
||||
EventTrigger targetObjET = targetUIObj.GetComponent<EventTrigger>();
|
||||
if (targetObjET == null)
|
||||
{
|
||||
targetObjET = targetUIObj.AddComponent<EventTrigger>();
|
||||
}
|
||||
triggerObjET.AddEventTrigger(EventTriggerType.PointerEnter, (eventData) => OnMouseIn(triggerUIObj));
|
||||
triggerObjET.AddEventTrigger(EventTriggerType.PointerExit, (eventData) => OnMouseOut(triggerUIObj));
|
||||
targetObjET.AddEventTrigger(EventTriggerType.PointerEnter, (eventData) => OnMouseIn(targetUIObj));
|
||||
targetObjET.AddEventTrigger(EventTriggerType.PointerExit, (eventData) => OnMouseOut(targetUIObj));
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Check mouse interactions to determine whether to slide in or out the UI.
|
||||
if ((isMouseInTrigger || isMouseInTarget) && isInActive)
|
||||
{
|
||||
SlideInScreen();
|
||||
isInActive = false;
|
||||
isOutActive = true;
|
||||
}
|
||||
else if (!isMouseInTrigger && !isMouseInTarget && isOutActive)
|
||||
{
|
||||
SlideOutScreen();
|
||||
isInActive = true;
|
||||
isOutActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseIn(GameObject type)
|
||||
{
|
||||
// Update flags based on which UI object the mouse enters.
|
||||
if (type == triggerUIObj)
|
||||
{
|
||||
isMouseInTrigger = true;
|
||||
}
|
||||
else if (type == targetUIObj)
|
||||
{
|
||||
isMouseInTarget = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseOut(GameObject type)
|
||||
{
|
||||
// Update flags based on which UI object the mouse exits.
|
||||
if (type == triggerUIObj)
|
||||
{
|
||||
isMouseInTrigger = false;
|
||||
}
|
||||
else if (type == targetUIObj)
|
||||
{
|
||||
isMouseInTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SlideInScreen()
|
||||
{
|
||||
// Animate the UI objects to slide in.
|
||||
triggerUIObj.transform.DOMove(triggerEndPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
targetUIObj.transform.DOMove(targetEndPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
}
|
||||
|
||||
private void SlideOutScreen()
|
||||
{
|
||||
// Animate the UI objects to slide out.
|
||||
triggerUIObj.transform.DOMove(triggerOriginalPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
targetUIObj.transform.DOMove(targetOriginalPosition, slideDuration).SetEase(Ease.OutCirc).Play();
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b459fcafb205c9540a282b421abdf6d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
155
README-JP.md
155
README-JP.md
@ -1,155 +0,0 @@
|
||||
# Aimbot-ParallelEnv
|
||||
これはUnity ML-Agentsに基づいたFPSゲームのマルチエージェントトレーニング環境で、特定の目標と対応する難易度を生成し、エージェントのアクションに基づいて報酬をフィードバックして強化学習エージェントをトレーニングするための環境です。
|
||||
|
||||
[![Chinese badge](https://img.shields.io/badge/简体中文-Simplified_Chinese-blue)](./README.md)
|
||||
[![Japanese badge](https://img.shields.io/badge/日本語-Japanese-blue)](./README-JP.md)
|
||||
|
||||
|
||||
## Description
|
||||
プロジェクトは[ML-Agents 2.0.1](https://github.com/Unity-Technologies/ml-agents/tree/develop)を基にして、Unity 2021.3.14f1を使用して開発されています。
|
||||
Python側では、[mlagents-envs 0.30.0](https://pypi.org/project/mlagents-envs/)を使用してゲーム環境と通信を行います。
|
||||
|
||||
## Quick start
|
||||
プロジェクト[Aimbot-PPO](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-PPO)では、この環境を使用してPPOアルゴリズムのトレーニングが行われています。具体的な使用例は[AimbotEnv.py](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-PPO/src/branch/OffP-FullMNN-V2/Aimbot-PPO-Python/Pytorch/AimbotEnv.py)で記載されています。
|
||||
|
||||
## ゲーム環境の概要
|
||||
本環境は初代Doomの基本モードを模したFPSゲームで、エージェントには異なる目標が与えられます。エージェントは目標の種類と位置、自身の状態に基づいて、撃つかどうか、撃つ方向、移動方向を決定します。この環境には2つのモードと3種類の目標があります:訓練モードとテストモード、そして`FreeTarget`、`GotoTarget`、`AttackTarget`です。`FreeTarget`では、エージェントは武器を使ってエリア内のすべての敵を倒す必要があります。`GotoTarget`と`AttackTarget`では、エリア内に目標ブロックが生成され、エージェントはそれに応じた異なる行動を取る必要があります。さらに、`GotoTarget`と`AttackTarget`では、生成される目標ブロックの構造に応じて5つの異なる難易度に分けられています。
|
||||
|
||||
## ゲームの概要
|
||||
この環境は初代Doomの基本モードを模したFPSゲームで、エージェントには異なる目標が与えられます。エージェントは目標の種類と位置、自身の状態に基づいて、撃つかどうか、撃つ方向、移動方向を決定します。この環境には2つのモードと3種類の目標があります:訓練モードとテストモード、そして`FreeTarget`、`GotoTarget`、`AttackTarget`です。`FreeTarget`では、エージェントは武器を使ってエリア内のすべての敵を倒す必要があります。`GotoTarget`と`AttackTarget`では、エリア内に目標ブロックが生成され、エージェントはそれに応じた異なる行動を取る必要があります。さらに、`GotoTarget`と`AttackTarget`では、生成される目標ブロックの構造によって、5つの異なる難易度に分けられています。
|
||||
|
||||
## モード
|
||||
訓練モードとテストモードは、Python側と通信が必要で、この環境から観測されたObservationに基づいてActionを生成し、環境にフィードバックします。環境を起動する際、ゲーム内でユーザーが操作してモードを選択する必要があります。ML-Agentsにはタイムリミットが存在するため、45秒以内にモードを選択する必要があります。45秒を超えると、自動的にゲーム環境から退出します。
|
||||
|
||||
### 訓練モード
|
||||
訓練モードに入る前に、手動でスタート画面から`Train-Free`、`Train-Goto`、`Train-Attack`(単一モードの訓練)または`Train-Mix`(全モードの訓練)の中から選択する必要があります。選択後、訓練モードに入りますが、この選択は後で変更できません。複数の難易度がある目標ブロック`Train-Goto`と`Train-Attack`のモードでは、スタート画面に異なる難易度の目標ブロックを生成する確率を調整するパネルが画面の左上にあります。デフォルトでは、各難易度の生成確率は均等となっています。このパネルでは、各モードの難易度の合計確率が1になるように、一つの難易度の確率を調整すると他の難易度の確率が自動的に調整されます。ユーザーは右側のロックボタンをクリックして、特定の難易度の確率をロックまたは解除することができます。このパネルは訓練モードの実行中にも表示され、ユーザーが訓練中に確率パネルを調整すると、次の目標ブロックの生成時に適用されます。
|
||||
<br>![TargetLevelProbabilityPanel](./ReadmeImages/LevelProbabilityPanel.jpg)
|
||||
|
||||
### テストモード
|
||||
テストモードでは、ユーザーが手動でエージェントに命令を指定する必要があります。画面右上のメニューをクリックすることで、目標ブロックや敵を生成したり、目標モードを切り替えたりすることができます。このモードでは、訓練モードにはない新しいターゲット`StayTarget`が追加されています。ユーザーが特定の目標を指定しない場合やゲームをクリアした場合、`StayTarget`がエージェントに割り当てられます。右上隅のメニューをクリックすると、マウスモードを切り替えて敵(Enemy)を生成するモードや、特定の難易度のターゲットブロックを生成するモードに変更できます。マウスがブロック生成モードで、マウスをゲームエリアに移動すると、生成するオブジェクトのプレビューが表示され、マウスの右クリックで指定した位置に対応する敵やブロックを生成できます。ターゲットブロックを生成すると、対応するターゲットが自動的にエージェントに割り当てられます。`FreeTarget`を割り当てる必要がある場合は、`FreeMode`ボタンをクリックします。`ClearGame`をクリックすると、すべての敵とブロックがクリアされ、エージェントのターゲットが`StayTarget`に設定されます。`StayMode`をクリックすると、エージェントのターゲットを強制的に`StayTarget`に設定できます。
|
||||
|
||||
## Target
|
||||
|
||||
### FreeTarget
|
||||
エージェントが`FreeTarget`に割り当てられた場合、エージェントはエリア内のすべての敵を武器で倒す必要があります。このモードでは、ラウンド開始時にエリア内にランダムな数の敵が生成されます(デフォルトは6体)。エージェントはエリアのランダムな位置に生成され、向きは前回のラウンドを引き継ぎます(最初のラウンドの場合はデフォルトで角度0)。エージェントがすべての敵を倒せば勝利と判断され、30秒以内にすべての敵を倒せない場合は失敗と判断されます。
|
||||
|
||||
### GotoTarget
|
||||
エージェントが`GotoTarget`に割り当てられた場合、指定された目標エリアの特定の位置に移動することが目標です。このモードでは、ラウンドが始まるとエージェントの位置は前のラウンドを引き継ぎます(最初のラウンドではマップの左下隅にデフォルトで生成されます)。Gotoの目標ブロックは、難易度の確率に応じてエリア内にランダムに生成され、異なる難易度には複数のプリセットブロックが用意されています。これらのプリセットブロックは[`SceneBlocksSet`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/TargetContainer/SceneBlocksSet.cs)によって[Prefabフォルダ](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Prefeb)に保存されています。すべての目標ブロックの合計サイズは10x10で、ブロックが生成される際にはエージェントの位置を避けます。指定された目標エリアは`FireBase`と呼ばれる円形のエリアで、その範囲は目標ブロックを超えることはありませんが、位置とサイズはプリセットブロックによって異なります。エージェントが目標ブロックの中心位置に正常に移動すると勝利と判断され、30秒以内に中心位置に移動できない場合は失敗と判断されます。
|
||||
|
||||
### AttackTarget
|
||||
エージェントが`AttackTarget`に割り当てられた場合、目標エリアに火力を集中し、主な目標はブロック内のすべての敵を倒すことです。このモードでのエージェントと目標ブロックの生成戦略、および`FireBase`の構成は`GotoTarget`と同様です。しかし、`AttackTarget`の`FireBase`エリア内には必ず敵が生成されます。エージェントがブロック内のすべての敵を倒せば勝利と判断され、30秒以内にすべての敵を倒せない場合は失敗と判断されます。
|
||||
|
||||
---
|
||||
# Environment
|
||||
## Observation Space
|
||||
本強化学習訓練設定では、状態(State)は環境を理解し、分析する上での鍵となります。観測環境は3つの主要な部分で構成されています:`TargetState`(ターゲット状態)、`AgentState`(自機状態)、そして`RaycastState`(レイキャスト状態)。これらの観測データはML-Agentsの`VectorSensor`クラスを通じて収集され、Python側に送信され、意思決定に必要な情報を提供します。Observationのソースコードは[`MLAgentsCustomController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/MLAgentsCustomController.cs)にあるoverrideされた`CollectObservations`関数内に格納されています。
|
||||
|
||||
### TargetState(ターゲット状態)
|
||||
`TargetState`は、エージェントが受け取ったTargetとその関連情報を含んで、合計六つあります。ターゲットの種類、x,y,z座標、TargetAreaの直径、そしてエージェントがTargetArea内にいるか、およびそのラウンドの残り時間などの情報を含みます。
|
||||
| 番号 | 観測項目 | サイズ | 状態空間 | 説明 |
|
||||
|------|-----------------|-------|------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| 0 | Targetの種類 | 1 | 0,1,2,3,4 | 割り当てられたTargetの種類を記述:0=FreeTarget、1=GotoTarget、2=AttackTarget、3=DefenceTarget(未使用)、4=StayTarget |
|
||||
| 1~3 | Targetの座標 | 3 | 0~47 | Target中のFirebaseの連続空間座標を記述、範囲は0から47の連続値 |
|
||||
| 4 | FireBaseの直径 | 1 | 1~10 | FireBaseの直径を記述、範囲は1から10の連続値 |
|
||||
| 5 | InFireBase状態 | 1 | 0,1 | エージェントがFireBase内にいるかどうかを記述、0=False、1=True |
|
||||
| 6 | 残り時間 | 1 | 0~30 | ラウンドの残り時間を記述、範囲は0から30の連続値 |
|
||||
|
||||
### AgentState(自機の状態)
|
||||
`AgentState`は、エージェントの武器が攻撃可能な状態かどうか、エージェントのx, y, z座標、およびエージェントの向きの角度を含んでいます。エージェントのGameObjectの向きの角度を直接使用すると、0から360度の変化時に値が大幅に変化してしまいます。より良い周期的な表現を実現するために、エージェントのGameObjectの回転角度のコサインとサインの値を使用してエージェントの向きを表しています。
|
||||
| 番号 | 観測項目 | サイズ | 状態空間 | 説明 |
|
||||
|------|------------|-------|---------|---------------------------------------------------------------------------------------|
|
||||
| 7 | GunState | 1 | 0,1 | エージェントの武器が使用可能な状態かどうかを記述。0=False、1=True |
|
||||
| 8~10 | エージェントの座標 | 3 | 0~47 | エージェントの連続空間座標を記述、範囲は0から47の連続値 |
|
||||
| 11~12| エージェントの向き | 2 | -1~1 | エージェントのGameObjectの回転角度のcosとsin値を計算してエージェントの正面の向きを記述。 |
|
||||
|
||||
### RaycastState(視野状態)
|
||||
`RaycastState`はエージェント視界内で発射されたレイキャストが検出したオブジェクトのタグとその距離を記録します。タグはラベルエンコーディングとワンホットエンコーディングの2つの方法で記録することができ、デフォルトではラベルエンコーディングが使用されます。これは`CommonParameterContainer`オブジェクトで調整することが可能です。`RaycastState`は[`RaySensors`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/RaySensors.cs)クラスによって管理されており、非均一なレイキャストの分布が実装されています。デフォルトでは、視界の中央15%のエリアに射線がより密集して分布し、両側はより希薄です。中央の密集エリアからは5本の射線が、両側の希薄エリアからはそれぞれ7本の射線が発射されます。各レイキャストが検出可能な最大距離は100ユニットで、その距離を超えると0が返されます。視界の中央エリアのカバー範囲、エリア内のレイキャスト数、検出可能な距離は、各`Agent`のGameObjectのInspectorで調整できます。
|
||||
<br><img src="./ReadmeImages/RayCastLayout.png" alt = "射線の分布方式" width="500" height = "auto">
|
||||
| 番号 | 観測項目 | サイズ | 状態空間 | 説明 |
|
||||
|-------------------------------------------------------------------|-------------------|---------------------|--------------|----------------------------------------------------------------------------------------|
|
||||
| 11~Raynum+11 | TagType(Label) | Raycast数 | 0, 1, 2 | レイキャストが検出した物体のタグ。0=Wall, 1=Enemy, 2=Player, -1=Nothing |
|
||||
| 11~Raynum * 3+11 | TagType(Onehot) | Raycast数 * 3 | 0, 1 | レイキャストが検出した物体のタグ。ワンホットエンコーディングで記録 |
|
||||
| Raynum+12~2* Raynum+12(ラベル),<br>3* Raynum+12~4* Raynum+12(ワンホット) | 距離 | Raycast数 | 0~MaxDistance| レイキャストが検出した物体までの距離。範囲は0〜MaxDistance。MaxDistanceのデフォルトは100 |
|
||||
|
||||
*注:nは各エージェントのRaycast数、MaxDistanceは各エージェントのレイキャストの最大探知距離を指します。*
|
||||
|
||||
## Action Space
|
||||
FPSゲームにおけるプレイヤーのキーボードとマウスの同時操作をシミュレートするため、本環境のActionSpaceは`Discrete Action`(離散動作)と`Continuous Action`(連続動作)の2つの部分に分かれています。`Discrete Action`はプレイヤーのキーボードによる離散的な操作を模擬し、`Continuous Action`はマウスによる連続的な操作を模擬します。両方のActionSpaceに対応する操作は[`MLAgentsCustomController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/MLAgentsCustomController.cs)内のoverrideされた`Heuristic`関数で参照できます。具体的な実装は[`AgentController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/Character/AgentController.cs)内の`MoveAgent`関数と`CameraControl`関数にあります。
|
||||
|
||||
### Discrete Action(離散動作)
|
||||
`Discrete Action`では、エージェントは各方向の移動と攻撃を離散的に操作できます。移動操作には垂直移動と水平移動が含まれ、攻撃操作では武器の操作が可能です。
|
||||
| 番号 | 動作 | ActionSpace | 説明 |
|
||||
|------|-------------------|----------------|---------------------------------------------------------------------------|
|
||||
| 0 | 垂直移動 | 0, 1, -1 | エージェントをその正面方向の垂直軸で制御。0=停止、1=前進、-1=後退 |
|
||||
| 1 | 水平移動 | 0, 1, -1 | エージェントをその正面方向の水平軸で制御。0=停止、1=右移動、-1=左移動 |
|
||||
| 2 | 攻撃 | 0, 1 | エージェントの攻撃操作を制御。0=攻撃しない、1=攻撃する |
|
||||
|
||||
### Continuous Action(連続動作)
|
||||
`Continuous Action`では、エージェントの視点を制御できます。本環境は初期のDoomのFPS環境を模擬しているため、エージェントの視点は水平方向のみで回転可能と設定されています。
|
||||
| 番号 | 動作 | ActionSpace | 説明 |
|
||||
|------|-------------------|----------------|---------------------------------------------------------------------------------|
|
||||
| 0 | 水平回転 | -Inf ~ Inf | エージェントの水平方向(左右)の視角回転を制御。正の値で右に、負の値で左に回転する。 |
|
||||
|
||||
## Reward
|
||||
与えられた各ターゲットにおいて、エージェントが異なるタスクを達成することに注力するため、リワードの設計もそれぞれ異なります。訓練モードでは、リワードは共通リワード「Common Reward」と各ターゲット専用のリワードで構成されています。
|
||||
|
||||
### Common Reward(共通リワード)
|
||||
エージェントが訓練中に目標達成に役立つ行動を取るように導き、無意味な動作を避けるために、`Common Reward`では以下のリワードとペナルティが設計されています。ML-AgentsはPythonに直接ラウンド終了の結果を伝えることができないため、他のリワードの値が小さすぎたり大きすぎたりして勝利または失敗を判断できない場合に備えて、ラウンド終了時のリワードには極大値と極小値が追加されています。
|
||||
| リワード/ペナルティ | 値/シンボル | 説明 |
|
||||
|-------------------|----------------|---------------------------------------------------------------|
|
||||
| 非ターゲット命中 | 3 | エージェントがターゲットではない敵を撃つか倒すと得られるリワード |
|
||||
| ターゲット命中 | 25 | エージェントがターゲットとなる敵を撃つか倒すと得られるリワード |
|
||||
| 移動ペナルティ | -0.5 | エージェントがフィールド上を移動するときに与えられるペナルティ |
|
||||
| 回転ペナルティ | $P_s$ | エージェントが視点を回転するときに与えられるペナルティ |
|
||||
| 勝利リワード | 999 | ラウンドが終了し、そのラウンドでエージェントが目標を達成したときに与えられるリワード |
|
||||
| 失敗リワード | 999 | ラウンドが終了し、そのラウンドでエージェントが失敗したときに与えられるリワード |
|
||||
|
||||
エージェントが訓練中に無意味な回転を行わないように、また回転速度が速すぎないように、以下の関数を使用して`SpinPenalty`を与えます。40個のマウス操作の回転記録が閾値に達していない場合、小さなペナルティが与えられます。閾値を超えると、エージェントが同じ方向に持続的に回転していることがわかるので、大きなペナルティが与えられます。ここでの<i>P<sub>s<sub>t</sub></sub></i>は時刻`t`の回転ペナルティ、<i>mouseX<sub>t</sub></i>は時刻`t`のエージェントの`Contunuouse Action`内の回転アクションの値を指します。
|
||||
|
||||
$$
|
||||
P_{st} =
|
||||
\begin{cases}
|
||||
-|mouseX_t| \cdot 0.06 &, & \left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| < 10 \\
|
||||
-\left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| & , & \left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| \geq 10
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
### FreeTarget
|
||||
`FreeTarget`では、主な目標は全ての敵を消滅させることです。そのため、敵を追跡する能力が非常に重要です。このモードでは、2種類の報酬メカニズムが設定されています:視界の中心で敵を検出した場合、エージェントには2の報酬が与えられます。敵を検出しなかった場合、視界の中心から検出された敵までの距離 \(D\) に基づいて2未満の報酬が与えられます。距離の計算は、Raycastで検出された敵にのみ考慮され、距離が0.5に近づくほど、つまり敵の半径がRewardに近づくほど、報酬は2に近づきます。たとえば、下図では`Enemy1`と`Enemy3`との距離のみが計算され、最短距離 \(D_1\) が報酬の計算に使用されます。検出されなかった`Enemy2`と`Enemy4`は除外されます。このモードでは、すべての敵がターゲットと見なされ、敵が倒されたり、ヒットした場合、エージェントは`Common Reward`の`TargetHit Reward`を獲得します。
|
||||
|
||||
<br><img src="./ReadmeImages/FreeTargetFacingreward.png" alt = "FacingReward" width="500" height = "auto">
|
||||
|
||||
| 報酬/ペナルティ | 値/記号 | 説明 |
|
||||
|----------------|----------------|-----------------------------------------|
|
||||
| FacingReward | \(R_f\) | 視界の中心と検出された最も近い敵との距離に基づく報酬 |
|
||||
|
||||
$$
|
||||
R_{f} =
|
||||
\begin{cases}
|
||||
2 &, &min(D) \leq 0.5 \\
|
||||
\frac{1}{\sqrt{\frac{min(D)}{2}}} &,& min(D) \gt 0.5
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
### GotoTarget
|
||||
`GotoTarget`では、主な目標は指定された`FireBase`への移動です。時刻 \(t\) と \(t-1\) でのプレイヤーとターゲット間の距離 \(D_t\) と \(D_{t-1}\) の差に基づいて、各ステップで獲得できる距離報酬 \(R_d\) が設定されています。エージェントが目標に近づくと正の報酬が与えられ、目標から離れると0未満のペナルティが与えられます。プレイヤーが`FireBase`内にいる場合、より高い固定報酬を得ることができますが、この場合`DistanceReward`は効果を発揮しません。このモードでは、すべての敵は攻撃対象とは見なされませんが、敵をヒットまたは倒した場合、`Common Reward`の`NonTargetHit`を獲得できます。
|
||||
|
||||
| 報酬/ペナルティ | 値/記号 | 説明 |
|
||||
|----------------|---------|----------------------------------------|
|
||||
| DistanceReward | \(R_d\) | エージェントが目標外にいる際の目標との距離差に基づく報酬 |
|
||||
| InAreaReward | 5 | エージェントが目標内にいる際の持続報酬 |
|
||||
|
||||
$$
|
||||
R_{d} = (D_{t-1} - D_{t}) \cdot 20
|
||||
$$
|
||||
|
||||
### AttackTarget
|
||||
`Attack Mode`では、主な目的は目標地点の敵を排除し、エージェントが目標地点に対して行動をとることを奨励することです。したがって、`FreeTarget`と同様に、目標地点への視線の移動も重要です。エージェントが目標地点に面して攻撃する場合、それは抑圧行動と見なされ、より低い`SuppressiveReward`が与えられます。目標地点に面しているが攻撃していない場合、さらに低い`FacingAreaReward`が継続して与えられます。`FireBase`内の敵は目標と見なされ、敵が倒されたりヒットした場合、エージェントは`Common Reward`の`TargetHit Reward`を獲得します。一方、`FireBase`外の敵は目標とは見なされず、敵が倒されたりヒットした場合、エージェントは`Common Reward`の`NonTargetHit Reward`のみを獲得します。
|
||||
|
||||
| 報酬/ペナルティ | 値/記号 | 説明 |
|
||||
|-----------------------|---------|------------------------------------------------|
|
||||
| SuppressiveReward | 5 | エージェントが`FireBase`に対して抑圧攻撃を行った際の報酬 |
|
||||
| FacingAreaReward | 2 | エージェントが目標に向かっている間の継続報酬 |
|
||||
|
||||
## Side Channel
|
||||
環境のデバッグやUnityとPython間の非リアルタイム通信を実現するため、この環境ではML-Agentsが提供するSide Channelを使用しています。ここではhuggingfaceの[Custom Side Channels](https://github.com/huggingface/ml-agents-patch/blob/develop/docs/Custom-SideChannels.md)をベースで開発を進みました。Unity側では、Side Channelの実装は[`AimbotSideChannel.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/SideChannel/AimbotSideChannel.cs)と[`AimBotSideChannelController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/SideChannel/AimBotSideChannelController.cs)に位置しています。各ログ情報は`|`でフィールドを区切り、最初のフィールドはログのタイプで、次のフィールドはカスタムログ情報です。この環境では、UnityのSide Channelはすべての`LogType.Warning`と`LogType.Error`タイプのログをPython側に送信します。`LogType.Warning`はラウンド終了後の勝敗情報やUnityからPythonへの指示を伝えます。勝敗情報は`Warning|Result|Win`や`Warning|Result|Lose`のようになります。一方、指令は次のトレーニング終了後にモデルを保存するコマンドで、その内容は`Warning|Command`となります。
|
143
README.md
143
README.md
@ -1,144 +1 @@
|
||||
# Aimbot-ParallelEnv
|
||||
这是一个基于Unity ML-Agents的基于FPS游戏的多智能体训练环境,用于生成指定目标和对应难度,并且根据Agent的Action反馈Reward来训练强化学习Agent的环境。
|
||||
|
||||
[![Chinese badge](https://img.shields.io/badge/简体中文-Simplified_Chinese-blue)](./README.md)
|
||||
[![Japanese badge](https://img.shields.io/badge/日本語-Japanese-blue)](./README-JP.md)
|
||||
|
||||
## Description
|
||||
项目基于[ML-Agents 2.0.1](https://github.com/Unity-Technologies/ml-agents/tree/develop),使用Unity 2021.3.14f1开发。
|
||||
Python侧则使用[mlagents-envs 0.30.0](https://pypi.org/project/mlagents-envs/)与环境进行通信。
|
||||
|
||||
## 快速开始
|
||||
在项目[Aimbot-PPO](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-PPO)中,使用了本环境进行了PPO算法的训练,其中在[AimbotEnv.py](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-PPO/src/branch/OffP-FullMNN-V2/Aimbot-PPO-Python/Pytorch/AimbotEnv.py)中给出了本环境的使用方法。
|
||||
|
||||
## 游戏简介
|
||||
这是一个模仿初代Doom的基本模式的FPS游戏环境,Agent将会被给到不同的目标,Agent需要根据目标的类型和位置,以及自身的状态,来决定是否开枪射击,射击的方向,以及移动方向。环境内包含两种模式和3种目标,分别是:训练模式和测试模式,以及`FreeTarget`,`GotoTarget`和`AttackTarget`。`FreeTarget`需要Agent使用武器击倒区域内所有的敌人,`GotoTarget`和`AttackTarget`会在区域内生成一个目标区块,Agent需要对目标区块进行不同的对应来完成任务。同时`GotoTarget`和`AttackTarget`中,根据生成目标区块的构造不同,分为了5种不同的难度。
|
||||
|
||||
## 模式介绍
|
||||
训练模式和测试模式都需要与Python侧进行通信,根据从本环境中观测到的Observation生成Action并传递回本环境。在环境启动时需要使用者在游戏内进行操作来选择模式,由于ML-Agents存在Time limit,所以需要在45s内进行模式选择,超过45s后将自动退出游戏环境。
|
||||
|
||||
### 训练模式
|
||||
在进入训练模式前,使用者需要从Start界面中,只训练单个模式的`Train-Free`,`Train-Goto`,`Train-Attack`和训练所有模式的`Train-Mix`中进行选择。在选择后,将会进入训练模式,并且注意该选择不能在之后进行更改。对于拥有多种难度的目标区块的模式`Train-Goto`和`Train-Attack`,在Start界面将会有一个用来调整生成不同难易度目标区块的概率的面板,默认的生成概率为平均。面板为了保证该模式各难易度生成概率总和为1,在调整某一难度的生成概率时,其他难度的生成概率将会被自动调整,用户可以通过点击右侧锁定按钮以锁定或解锁某一难度的生成概率。该面板将在训练模式执行中也可见,用户在训练模式执行中对概率面板进行调整后将会在应用在下次目标区块生成时。
|
||||
<br>![TargetLevelProbabilityPanel](./ReadmeImages/LevelProbabilityPanel.jpg)
|
||||
|
||||
### 测试模式
|
||||
测试模式中,用户需要手动来对Agent下达命令,用户可以通过点击右上角的菜单来执行生成目标区块或敌人,切换目标模式等。在该模式中,比训练模式多出一个新的Target为StayTarget,当用户未指定目标或者清空游戏时将会以将该Target指派给Agent。通过点击右上角的菜单,可以将鼠标的模式切换为生成Enemy,或者生成对应难度Target区块的模式,此时鼠标移动到游戏区域内后将会出现生成物件的预览,内点击鼠标右键则可以在对应的位置生成对应的Enemy或者区块。当生成Target区块时会自动指派对应target给agent,需要指派`FreeTarget`时则需要点击`FreeMode`按钮。通过点击`ClearGame`可以清空所有enemy和区块并将Agent的目标指派为`StayTarget`,通过点击`StayMode`则可以强制将Agent目标指派为`StayTarget`。
|
||||
|
||||
## 目标介绍
|
||||
|
||||
### FreeTarget
|
||||
在Agent被指派到`FreeTarget`时,Agent需要使用武器击倒区域内所有的敌人。在该模式中,一个回合开始时将会在区域内随机生成一定数量的敌人,默认为6,Agent将会生成在区域的随机位置,Agent朝向继承上一回合,如果是第一回合则是默认角度为0。Agent在成功击倒所有敌人后被判断为胜利,或者超过30s未能成功击倒所有敌人则被判断为失败。
|
||||
|
||||
### GotoTarget
|
||||
在Agent被指派到`GotoTarget`时,Agent的目标是移动到指定目标区块的指定位置。在该模式中,一个回合开始时Agent的位置总是继承上一个回合,如果是第一回合将会默认生成在地图的左下角。Goto的目标区块将会根据难度概率在区域内随机生成对应难度的预设区块,不同难易度拥有多个已保存好的预设区块,这些预设区块通过[`SceneBlocksSet`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/TargetContainer/SceneBlocksSet.cs)保存在[Prefab文件夹](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Prefeb)中。所有目标区块的总大小为10*10,生成目标区块时区块将会避开Agent的所在位置。指定目标区域是名为`FireBase`的圆形区域,该区域所覆盖的范围不会超过目标区块,但是它的位置和大小会根据预设区块的不同而不同。Agent在成功移动到目标区块中心位置后被判断为胜利,或者超过30s未能成功移动到目标区块中心位置则被判断为失败。
|
||||
|
||||
### AttackTarget
|
||||
在Agent被指派到`AttackTarget`时,Agent的目标是对目标区域进行火力压制,同时主要目标是击倒区块内所有敌人。在该模式中,Agent与目标区块的生成策略还有`FireBase`的构成与`GotoTarget`相同。但是在`AttackTarget`的`FireBase`区域内必定会有Enemy生成。Agent在成功击倒区块内所有敌人后被判断为胜利,或者超过30s未能成功击倒区块内所有敌人则被判断为失败。
|
||||
|
||||
---
|
||||
# Environment
|
||||
## Observation Space
|
||||
在本强化学习训练设置中,观测数据是理解和交互环境的关键。观测环境由三个主要部分组成:`TargetState`(目标状态)、`AgentState`(自机状态)和`RaycastState`(射线探测状态)。这些观测数据通过ML-Agents的`VectorSensor`类进行收集,并发送给Python侧,为决策提供必要的信息。Observation的Source Code位于[`MLAgentsCustomController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/MLAgentsCustomController.cs)中被override的`CollectObservations`函数中。
|
||||
|
||||
### TargetState(目标状态)
|
||||
`TargetState`包含了Agent接收的目标指令和相关信息,总大小为6。其中包含Target的类型,Target的x,y,z坐标,TargetArea的直径,以及Agent是否处于TargetArea和本回合剩余时间内这些信息。
|
||||
| Num | Observation | Size | State Space | Description |
|
||||
|-----|------------------|------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||
| 0 | Target类型 | 1 | 0,1,2,3,4 | 描述被指派的Target类型:0=FreeTarget,1=GotoTarget,2=AttackTarget,3=DefenceTarget(未使用),4=StayTarget |
|
||||
| 1~3 | Target坐标 | 3 | 0~47 | 描述Target中Firebase的连续空间坐标,取值范围为0到47之间的连续值 |
|
||||
| 4 | FireBaseDiameter | 1 | 1~10 | 描述FireBase的直径,取值范围为在1到10之间的连续值 |
|
||||
| 5 | InFireBaseState | 1 | 0,1 | 描述Agent是否处于FireBase中,0=False,1=True |
|
||||
| 6 | RemainTime | 1 | 0~30 | 描述本回合剩余时间,取值范围为在0到30之间的连续值 |
|
||||
### AgentState(自机状态)
|
||||
`AgentState`包含了Agent的武器可攻击状态,Agent的x,y,z坐标和Agent的朝向角度。为了避免直接使用Agent GameObject朝向角度时,0到360度变化时值的大幅度跳变,同时为了实现更好的周期性表示,这里使用了Agent GameObject旋转角度的余弦和正弦值来表示Agent的朝向。
|
||||
| Num | Observation | Size | State Space | Description |
|
||||
|------|-------------|------|-------------|---------------------------------------------------------------------|
|
||||
| 7 | GunState | 1 | 0,1 | 描述Agent武器是否处于可使用状态。0=False,1=True |
|
||||
| 8~10 | Agent坐标 | 3 | 0~47 | 描述Agent的连续空间坐标,取值范围为0到47之间的连续值 |
|
||||
| 11~12 | Agent朝向 | 2 | -1~1 | 通过计算Agent GameObject旋转角度的余弦和正弦以描述Agent的正面朝向。 |
|
||||
### RaycastState(射线探测状态)
|
||||
`RaycastState`记录了视野内发射的射线探测到的Object的Tag及其距离、其中Tag可以通过Label Encoding和OneHot Encoding两种方式来记录,默认使用Label Encoding,可以在Object`CommonParameterContainer`中进行调整。`RaycastState`由[`RaySensors`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/RaySensors.cs)类管理。它实现了射线的非均匀分布,默认视野中间15%的区域射线分布更密集,两侧则较为稀疏,默认中间密集部分共射出5条,两侧稀疏部分各7条。 每个射线可探测的对象最远距离为100个单位,超过探测距离则返回0。其中视野中间区域的覆盖范围,区域内RayCast数量以及可探测距离均可以在每个`Agent`GameObject的Inspector中进行调整。
|
||||
<br><img src="./ReadmeImages/RayCastLayout.png" alt = "射线分布方式" width="500" height = "auto">
|
||||
| Num | Observation | Size | State Space | Description |
|
||||
|------------------------------------------------------------------|-----------------|--------------------|---------------|----------------------------------------------------------------------------------|
|
||||
| 11~Raynum+11 | TagType(Label) | Number of Raycasts | 0, 1, 2 | 描述Raycast所探测到物体的Tag, 0=Wall, 1=Enemy, 2=Player, -1=Nothing |
|
||||
| 11~Raynum * 3+11 | TagType(Onehot) | Raynum * 3 | 0, 1 | 描述Raycast所探测到物体的Tag, 使用Onehot编码记录 |
|
||||
| Raynum+12~2* Raynum+12(Label),<br>3* Raynum+12~4* Raynum+12(OneHot) | Distance | Number of Raycasts | 0~MaxDistance | 描述Raycast所探测到物体的距离,取值范围在0~MaxDistance,其中MaxDistance默认为100 |
|
||||
|
||||
*注:n为每个Agent的RayCast数量,MaxDistance为每个Agent的RayCast最大探测距离*
|
||||
|
||||
## Action Space
|
||||
为了模拟FPS游戏中玩家对于键盘和鼠标的同时操作,本环境中的Action Space分为两个部分,分别是`Discrete Action`和`Continuous Action`。其中`Discrete Action`用于模拟玩家对于键盘的离散操作,`Continuous Action`用于模拟玩家对于鼠标的连续操作。两个Action Space的对应操作可以参考于[`MLAgentsCustomController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/MLAgentsCustomController.cs)中被override的`Heuristic`函数。具体实现则于[`AgentController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/Character/AgentController.cs)中的`MoveAgent`和`CameraControl`函数中。
|
||||
|
||||
### Discrete Action
|
||||
在`Discrete Action`中,Agent可以对各方向的移动和攻击进行离散操作,其中移动操作包括垂直移动操作和水平移动操作,攻击操作可以对武器进行操。
|
||||
| Num | Action | Action Space | Description |
|
||||
|-----|-----------------|--------------|---------------------------------------------------------------------------|
|
||||
| 0 | Vertical Move | 0,1,-1 | 用于控制Agent在其正面方向的垂直轴上移动。0=停止,1=向前移动,-1=向后移动 |
|
||||
| 1 | Horizontal Move | 0,1,-1 | 用于控制Agent在其正面方向的水平轴上移动。0=停止,1=向右移动,-1=向左移动 |
|
||||
| 2 | Attack | 0,1 | 用于控制Agent的攻击操作。0=不攻击,1=执行攻击 |
|
||||
|
||||
### Continuous Action
|
||||
在`Continuous Action`中,可以对Agent的视角进行操作。由于本环境是模拟早期Doom的FPS环境,所以Agent的视角被设定为仅能在水平方向上进行旋转。
|
||||
| Num | Action | Action Space | Description |
|
||||
|-----|-------------------|--------------|---------------------------------------------------------------------------------|
|
||||
| 0 | Vertical Rotation | -Inf~Inf | 控制Agent在水平方向(左右)上的视角旋转。正值使视角向右,负值则使视角向左旋转。 |
|
||||
|
||||
## Reward
|
||||
在各给定的目标中,为了让Agent注重于完成不同的任务,Reward的设计也有所不同。在训练模式中,Reward由共同Reward`Common Reward`和各个目标的专用Reward组成。
|
||||
### Common Reward
|
||||
为了引导Agent在训练过程中执行对完成目标有帮助的操作,和避免无意义的动作,在`Common Reward`中,环境为Agent设计了以下的Reward和Penalty。其中由于ML-Agents不能向Python直接传递回合结束的结果,同时为了避免其他Reward数值过小或者过大导致无法判断胜利或者失败,因此在回合结束的Reward中添加了极大数和极小数来表示胜利和失败。
|
||||
| Reward/Penalty | Value/Symbol | Description |
|
||||
|----------------|---------------|-----------------------------------------------------|
|
||||
| NonTargetHit | 3 | 当Agent击中或者击倒不作为Target的敌人时所获得Reward |
|
||||
| TargetHit | 25 | 当Agent击中或者击倒作为Target的敌人时所获得Reward |
|
||||
| MovePenalty | -0.5 | 当Agent在场地中移动时给到的Penalty |
|
||||
| SpinPenalty | $P_s$ | 当Agent进行视角旋转时给到的Penalty |
|
||||
| WinReward | 999 | 当回合结束并且本回合Agent达成目标时给到的Reward |
|
||||
| LoseReward | 999 | 当回合结束并且本回合Agent失败时给到的Reward |
|
||||
|
||||
为了防止Agent在训练中出现无意义的旋转,和旋转过快,这里用下列函数来给到Agent一个`SpinPenalty`。当40个Action的旋转记录未达到阈值时会给到一个较小的Penalty,而当超过阈值时我们可以知道Agent正在向同一方向持续旋转,则给到一个较大的Penalty。其中<i>P<sub>s<sub>t</sub></sub></i>为在`t`时刻时的旋转的Penalty,<i>mouseX<sub>t</sub></i>为`t`时刻Agent的`Contunuouse Action`中的旋转Action数值。
|
||||
$$
|
||||
P_{st} =
|
||||
\begin{cases}
|
||||
-|mouseX_t| \cdot 0.06 &, & \left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| < 10 \\
|
||||
-\left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| & , & \left| \sum_{t=0}^{-40} mouseX_t \cdot 0.08 \right| \geq 10
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
### FreeTarget
|
||||
在`FreeTarget`中,主要目标是消灭所有敌人,因此,追踪敌人的能力非常关键。本模式设置了两种奖励机制:当视野中心探测到敌人时给到Agent一个为2的Reward,当未探测到敌人时,则根据探测到的敌人距离视野中心的距离 $D$ 给到一个小于`2`的Reward。距离的计算仅考虑通过 Raycast 探测到的敌人,且当距离越接近0.5,即Enemy半径则Reward越接近`2`。例如,在图中,只计算了与`Enemy1`和`Enemy3`的距离,并且取用最短距离 $D_1$ 来计算Reward。未探测到的`Enemy2`和`Enemy4`被排除在外。在这个模式下,所有敌人都被视为目标,当敌人被击败或击中时,Agent 将获得`Common Reward`中的`TargetHit Reward`。
|
||||
<br><img src="./ReadmeImages/FreeTargetFacingreward.png" alt = "FacingReward" width="500" height = "auto">
|
||||
|
||||
| Reward/Penalty | Value/Symbol | Description |
|
||||
|----------------|----------------------|----------------------------------------|
|
||||
| FacingReward | $R_f$ | 视野中心与所探测到最近敌人距离的Reward |
|
||||
|
||||
$$
|
||||
R_{f} =
|
||||
\begin{cases}
|
||||
2 &, &min(D) \leq 0.5 \\
|
||||
\frac{1}{\sqrt{\frac{min(D)}{2}}} &,& min(D) \gt 0.5
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
### GotoTarget
|
||||
在`GotoTarget`中,主要目标是向指定的`FireBase`移动。根据在`t`时刻和`t-1`时刻的玩家与目标间的距离 $D_t$ 和 $D_{t-1}$ 的差值,设置了每个 Step 可获得的距离奖励 $R_d$ 。当Agent接近目标时将获得正向Reward,远离目标时则获得小于0的Penalty。当玩家处于`FireBase`内时,可以获得更高的固定奖励,然而此时`DistanceReward`将不会生效。在此模式中,所有敌人均不被视为攻击目标,但在击中或击败敌人时,可以获得`Common Reward`中的`NonTargetHit`。
|
||||
| Reward/Penalty | Value/Symbol | Description |
|
||||
|----------------|--------------|-----------------------------------------|
|
||||
| DistanceReward | $R_d$ | Agent不在目标内时,和目标的距离差Reward |
|
||||
| InAreaReward | 5 | Agent处于目标内时的持续奖励 |
|
||||
|
||||
$$
|
||||
R_{d} = (D_{t-1} - D_{t}) \cdot 20
|
||||
$$
|
||||
|
||||
### AttackTarget
|
||||
在 Attack Mode 中,主要目的是消灭目标地点的敌人并鼓励Agent对目标地点进行设计。因此与`FreeTarget`类似,将视线移动到目标地点同样重要。当Agent面对目标地点并且进行攻击时,将会被视为压制行为,并获得较低的`SuppressiveReward`。面对目标地点但未进行攻击时,获得持续获得更低的`FacingAreaReward`。处于`FireBase`中的Enemy将会被视为目标,当敌人被击败或击中时,Agent 将获得`Common Reward`中的`TargetHit Reward`。而`FireBase`外的敌人则不会被视为目标,当敌人被击败或击中时,Agent 将只能获得`Common Reward`中的`NonTargetHit Reward`。
|
||||
| Reward/Penalty | Value/Symbol | Description |
|
||||
|-------------------|--------------|-----------------------------------------|
|
||||
| SuppressiveReward | 5 | Agent对`FireBase`进行压制攻击时获得奖励 |
|
||||
| FacingAreaReward | 2 | Agent面朝目标时获得的持续奖励 |
|
||||
|
||||
## Side Channel
|
||||
为了方便对于环境的调试和实现Unity与Python间非实时通信,本环境中使用了ML-Agents提供的Side Channel,用于向Python侧传递一些额外的信息。这里我参考了huggingface的[Custom Side Channels](https://github.com/huggingface/ml-agents-patch/blob/develop/docs/Custom-SideChannels.md)。在Unity端,Side Channel的实现位于[`AimbotSideChannel.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/SideChannel/AimbotSideChannel.cs)和[`AimBotSideChannelController.cs`](https://koha9.asuscomm.com/yurugit/Koha9/Aimbot-ParallelEnv/src/branch/main/Assets/Script/GameScript/SideChannel/AimBotSideChannelController.cs)中。每个Log信息将会以`|`来分隔字段,其中第一个字段为Log的类型,随后字段为自定义Log信息。在本环境中,Unity的SideChannel将会发送所有`LogType.Warning`和`LogType.Error`类型的Log到Python侧。其中`LogType.Warning`会传递一回合结束后的的胜败信息和从Unity发送至Python的指令。胜败信息将类似于`Warning|Result|Win`和`Warning|Result|Lose`。而指令则传递了在下一训练结束后保存模型的命令,它的内容为`Warning|Command`。
|
BIN
ReadmeImages/FreeTargetFacingreward.png
(Stored with Git LFS)
BIN
ReadmeImages/FreeTargetFacingreward.png
(Stored with Git LFS)
Binary file not shown.
BIN
ReadmeImages/LevelProbabilityPanel.jpg
(Stored with Git LFS)
BIN
ReadmeImages/LevelProbabilityPanel.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
ReadmeImages/RayCastLayout.png
(Stored with Git LFS)
BIN
ReadmeImages/RayCastLayout.png
(Stored with Git LFS)
Binary file not shown.
@ -9,13 +9,13 @@ EditorUserSettings:
|
||||
value: 55090405535008090b5608764626074415151c79747c74602b7c1861e4b96c6c
|
||||
flags: 0
|
||||
RecentlyUsedSceneGuid-1:
|
||||
value: 5453565f53020f085f5d0e72157a0844454f4c2b757d7265757a4f64b7b4313c
|
||||
value: 06570c0704040b0e5a575520137b5e44154f192e292d22367c2c4866b7b3376f
|
||||
flags: 0
|
||||
RecentlyUsedSceneGuid-2:
|
||||
value: 5703025650035e5d090f087148715d4443161e2c7e2c20357b281b31b0e43060
|
||||
value: 5453565f53020f085f5d0e72157a0844454f4c2b757d7265757a4f64b7b4313c
|
||||
flags: 0
|
||||
RecentlyUsedSceneGuid-3:
|
||||
value: 06570c0704040b0e5a575520137b5e44154f192e292d22367c2c4866b7b3376f
|
||||
value: 5703025650035e5d090f087148715d4443161e2c7e2c20357b281b31b0e43060
|
||||
flags: 0
|
||||
RecentlyUsedScenePath-0:
|
||||
value: 22424703114646680e0b0227036c6c111b07142f1f2b233e2867083debf42d
|
||||
|
@ -1,30 +1,6 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &1
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_PixelRect:
|
||||
serializedVersion: 2
|
||||
x: -1015
|
||||
y: -63
|
||||
width: 963
|
||||
height: 708
|
||||
m_ShowMode: 0
|
||||
m_Title: Game
|
||||
m_RootView: {fileID: 4}
|
||||
m_MinSize: {x: 100, y: 121}
|
||||
m_MaxSize: {x: 4000, y: 4021}
|
||||
m_Maximized: 0
|
||||
--- !u!114 &2
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -38,67 +14,17 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_PixelRect:
|
||||
serializedVersion: 2
|
||||
x: 535
|
||||
y: 182
|
||||
width: 1175
|
||||
height: 749
|
||||
x: -21
|
||||
y: 128
|
||||
width: 1855
|
||||
height: 1037
|
||||
m_ShowMode: 4
|
||||
m_Title: Hierarchy
|
||||
m_RootView: {fileID: 5}
|
||||
m_Title: Game
|
||||
m_RootView: {fileID: 2}
|
||||
m_MinSize: {x: 875, y: 300}
|
||||
m_MaxSize: {x: 10000, y: 10000}
|
||||
m_Maximized: 0
|
||||
--- !u!114 &3
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: GameView
|
||||
m_EditorClassIdentifier:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 963
|
||||
height: 708
|
||||
m_MinSize: {x: 100, y: 121}
|
||||
m_MaxSize: {x: 4000, y: 4021}
|
||||
m_ActualView: {fileID: 17}
|
||||
m_Panes:
|
||||
- {fileID: 17}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 0
|
||||
--- !u!114 &4
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Children:
|
||||
- {fileID: 3}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 963
|
||||
height: 708
|
||||
m_MinSize: {x: 100, y: 121}
|
||||
m_MaxSize: {x: 4000, y: 4021}
|
||||
vertical: 0
|
||||
controlID: 105
|
||||
--- !u!114 &5
|
||||
--- !u!114 &2
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -111,22 +37,22 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Children:
|
||||
- {fileID: 6}
|
||||
- {fileID: 8}
|
||||
- {fileID: 7}
|
||||
- {fileID: 3}
|
||||
- {fileID: 5}
|
||||
- {fileID: 4}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1175
|
||||
height: 749
|
||||
width: 1855
|
||||
height: 1037
|
||||
m_MinSize: {x: 875, y: 300}
|
||||
m_MaxSize: {x: 10000, y: 10000}
|
||||
m_UseTopView: 1
|
||||
m_TopViewHeight: 30
|
||||
m_UseBottomView: 1
|
||||
m_BottomViewHeight: 20
|
||||
--- !u!114 &6
|
||||
--- !u!114 &3
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -143,12 +69,12 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1175
|
||||
width: 1855
|
||||
height: 30
|
||||
m_MinSize: {x: 0, y: 0}
|
||||
m_MaxSize: {x: 0, y: 0}
|
||||
m_LastLoadedLayoutName:
|
||||
--- !u!114 &7
|
||||
--- !u!114 &4
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -164,12 +90,12 @@ MonoBehaviour:
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 729
|
||||
width: 1175
|
||||
y: 1017
|
||||
width: 1855
|
||||
height: 20
|
||||
m_MinSize: {x: 0, y: 0}
|
||||
m_MaxSize: {x: 0, y: 0}
|
||||
--- !u!114 &8
|
||||
--- !u!114 &5
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -182,19 +108,98 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Children:
|
||||
- {fileID: 6}
|
||||
- {fileID: 9}
|
||||
- {fileID: 12}
|
||||
- {fileID: 15}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 30
|
||||
width: 1175
|
||||
height: 699
|
||||
width: 1855
|
||||
height: 987
|
||||
m_MinSize: {x: 300, y: 200}
|
||||
m_MaxSize: {x: 24288, y: 16192}
|
||||
vertical: 0
|
||||
controlID: 52
|
||||
controlID: 28
|
||||
--- !u!114 &6
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Children:
|
||||
- {fileID: 7}
|
||||
- {fileID: 8}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1038
|
||||
height: 987
|
||||
m_MinSize: {x: 100, y: 200}
|
||||
m_MaxSize: {x: 8096, y: 16192}
|
||||
vertical: 1
|
||||
controlID: 16
|
||||
--- !u!114 &7
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 1
|
||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: GameView
|
||||
m_EditorClassIdentifier:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1038
|
||||
height: 594
|
||||
m_MinSize: {x: 101, y: 121}
|
||||
m_MaxSize: {x: 4001, y: 4021}
|
||||
m_ActualView: {fileID: 14}
|
||||
m_Panes:
|
||||
- {fileID: 14}
|
||||
- {fileID: 13}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 1
|
||||
--- !u!114 &8
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: ProjectBrowser
|
||||
m_EditorClassIdentifier:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 594
|
||||
width: 1038
|
||||
height: 393
|
||||
m_MinSize: {x: 231, y: 271}
|
||||
m_MaxSize: {x: 10001, y: 10021}
|
||||
m_ActualView: {fileID: 15}
|
||||
m_Panes:
|
||||
- {fileID: 15}
|
||||
- {fileID: 16}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 1
|
||||
--- !u!114 &9
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
@ -212,93 +217,15 @@ MonoBehaviour:
|
||||
- {fileID: 11}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
x: 1038
|
||||
y: 0
|
||||
width: 609
|
||||
height: 699
|
||||
width: 405
|
||||
height: 987
|
||||
m_MinSize: {x: 100, y: 200}
|
||||
m_MaxSize: {x: 8096, y: 16192}
|
||||
vertical: 1
|
||||
controlID: 53
|
||||
controlID: 29
|
||||
--- !u!114 &10
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 1
|
||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: SceneView
|
||||
m_EditorClassIdentifier:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 609
|
||||
height: 501
|
||||
m_MinSize: {x: 201, y: 221}
|
||||
m_MaxSize: {x: 4001, y: 4021}
|
||||
m_ActualView: {fileID: 16}
|
||||
m_Panes:
|
||||
- {fileID: 16}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 0
|
||||
--- !u!114 &11
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: ProjectBrowser
|
||||
m_EditorClassIdentifier:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 501
|
||||
width: 609
|
||||
height: 198
|
||||
m_MinSize: {x: 231, y: 271}
|
||||
m_MaxSize: {x: 10001, y: 10021}
|
||||
m_ActualView: {fileID: 18}
|
||||
m_Panes:
|
||||
- {fileID: 18}
|
||||
- {fileID: 19}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 1
|
||||
--- !u!114 &12
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Children:
|
||||
- {fileID: 13}
|
||||
- {fileID: 14}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 609
|
||||
y: 0
|
||||
width: 336
|
||||
height: 699
|
||||
m_MinSize: {x: 100, y: 200}
|
||||
m_MaxSize: {x: 8096, y: 16192}
|
||||
vertical: 1
|
||||
controlID: 78
|
||||
--- !u!114 &13
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -315,16 +242,16 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 336
|
||||
height: 392
|
||||
width: 405
|
||||
height: 611
|
||||
m_MinSize: {x: 202, y: 221}
|
||||
m_MaxSize: {x: 4002, y: 4021}
|
||||
m_ActualView: {fileID: 20}
|
||||
m_ActualView: {fileID: 17}
|
||||
m_Panes:
|
||||
- {fileID: 20}
|
||||
- {fileID: 17}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 0
|
||||
--- !u!114 &14
|
||||
--- !u!114 &11
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -340,18 +267,18 @@ MonoBehaviour:
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 392
|
||||
width: 336
|
||||
height: 307
|
||||
m_MinSize: {x: 102, y: 121}
|
||||
m_MaxSize: {x: 4002, y: 4021}
|
||||
m_ActualView: {fileID: 21}
|
||||
y: 611
|
||||
width: 405
|
||||
height: 376
|
||||
m_MinSize: {x: 100, y: 100}
|
||||
m_MaxSize: {x: 4000, y: 4000}
|
||||
m_ActualView: {fileID: 18}
|
||||
m_Panes:
|
||||
- {fileID: 21}
|
||||
- {fileID: 22}
|
||||
- {fileID: 18}
|
||||
- {fileID: 19}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 1
|
||||
--- !u!114 &15
|
||||
--- !u!114 &12
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -366,18 +293,18 @@ MonoBehaviour:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 945
|
||||
x: 1443
|
||||
y: 0
|
||||
width: 230
|
||||
height: 699
|
||||
width: 412
|
||||
height: 987
|
||||
m_MinSize: {x: 276, y: 71}
|
||||
m_MaxSize: {x: 4001, y: 4021}
|
||||
m_ActualView: {fileID: 23}
|
||||
m_ActualView: {fileID: 20}
|
||||
m_Panes:
|
||||
- {fileID: 23}
|
||||
- {fileID: 20}
|
||||
m_Selected: 0
|
||||
m_LastSelected: 0
|
||||
--- !u!114 &16
|
||||
--- !u!114 &13
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -397,10 +324,10 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 535
|
||||
y: 212
|
||||
width: 608
|
||||
height: 480
|
||||
x: 65
|
||||
y: 73
|
||||
width: 1037
|
||||
height: 573
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
@ -421,9 +348,9 @@ MonoBehaviour:
|
||||
floating: 0
|
||||
collapsed: 0
|
||||
displayed: 1
|
||||
snapOffset: {x: 0, y: 149}
|
||||
snapOffset: {x: -141, y: 149}
|
||||
snapOffsetDelta: {x: 0, y: 0}
|
||||
snapCorner: 0
|
||||
snapCorner: 1
|
||||
id: unity-grid-and-snap-toolbar
|
||||
index: 1
|
||||
layout: 1
|
||||
@ -497,7 +424,7 @@ MonoBehaviour:
|
||||
containerId: overlay-container--right
|
||||
floating: 0
|
||||
collapsed: 0
|
||||
displayed: 0
|
||||
displayed: 1
|
||||
snapOffset: {x: 0, y: 0}
|
||||
snapOffsetDelta: {x: 0, y: 0}
|
||||
snapCorner: 0
|
||||
@ -635,9 +562,9 @@ MonoBehaviour:
|
||||
m_PlayAudio: 0
|
||||
m_AudioPlay: 0
|
||||
m_Position:
|
||||
m_Target: {x: 462, y: 315.5, z: 0}
|
||||
m_Target: {x: -93.190475, y: 4.007041, z: -23.907015}
|
||||
speed: 2
|
||||
m_Value: {x: 461.9999, y: 315.5, z: -0.00004226652}
|
||||
m_Value: {x: -93.190475, y: 4.007041, z: -23.907015}
|
||||
m_RenderMode: 0
|
||||
m_CameraMode:
|
||||
drawMode: 0
|
||||
@ -684,13 +611,13 @@ MonoBehaviour:
|
||||
m_GridAxis: 1
|
||||
m_gridOpacity: 0.529
|
||||
m_Rotation:
|
||||
m_Target: {x: -0.31611243, y: -0.22831854, z: 0.078667216, w: -0.9174724}
|
||||
m_Target: {x: -0.04341376, y: 0.5871053, z: 0.031550582, w: 0.80778545}
|
||||
speed: 2
|
||||
m_Value: {x: -0.31611243, y: -0.22831854, z: 0.07866721, w: -0.9174724}
|
||||
m_Value: {x: -0.043411803, y: 0.5870788, z: 0.03154916, w: 0.80774903}
|
||||
m_Size:
|
||||
m_Target: 10
|
||||
m_Target: 12.124355
|
||||
speed: 2
|
||||
m_Value: 10
|
||||
m_Value: 12.124355
|
||||
m_Ortho:
|
||||
m_Target: 0
|
||||
speed: 2
|
||||
@ -708,14 +635,14 @@ MonoBehaviour:
|
||||
m_FarClip: 10000
|
||||
m_DynamicClip: 1
|
||||
m_OcclusionCulling: 0
|
||||
m_LastSceneViewRotation: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
|
||||
m_LastSceneViewRotation: {x: -0.23316237, y: -0.24425557, z: 0.060633, w: -0.93931496}
|
||||
m_LastSceneViewOrtho: 0
|
||||
m_ReplacementShader: {fileID: 0}
|
||||
m_ReplacementString:
|
||||
m_SceneVisActive: 1
|
||||
m_LastLockedObject: {fileID: 0}
|
||||
m_ViewIsLockedToObject: 0
|
||||
--- !u!114 &17
|
||||
--- !u!114 &14
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -735,10 +662,10 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: -1015
|
||||
y: -63
|
||||
width: 963
|
||||
height: 687
|
||||
x: -21
|
||||
y: 158
|
||||
width: 1037
|
||||
height: 573
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
@ -746,17 +673,17 @@ MonoBehaviour:
|
||||
m_SerializedViewNames: []
|
||||
m_SerializedViewValues: []
|
||||
m_PlayModeViewName: GameView
|
||||
m_ShowGizmos: 0
|
||||
m_ShowGizmos: 1
|
||||
m_TargetDisplay: 0
|
||||
m_ClearColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_TargetSize: {x: 963, y: 666}
|
||||
m_TargetSize: {x: 1037, y: 552}
|
||||
m_TextureFilterMode: 0
|
||||
m_TextureHideFlags: 61
|
||||
m_RenderIMGUI: 1
|
||||
m_EnterPlayModeBehavior: 0
|
||||
m_UseMipMap: 0
|
||||
m_VSyncEnabled: 0
|
||||
m_Gizmos: 0
|
||||
m_Gizmos: 1
|
||||
m_Stats: 0
|
||||
m_SelectedSizes: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
m_ZoomArea:
|
||||
@ -764,10 +691,10 @@ MonoBehaviour:
|
||||
m_VRangeLocked: 0
|
||||
hZoomLockedByDefault: 0
|
||||
vZoomLockedByDefault: 0
|
||||
m_HBaseRangeMin: -481.5
|
||||
m_HBaseRangeMax: 481.5
|
||||
m_VBaseRangeMin: -333
|
||||
m_VBaseRangeMax: 333
|
||||
m_HBaseRangeMin: -518.5
|
||||
m_HBaseRangeMax: 518.5
|
||||
m_VBaseRangeMin: -276
|
||||
m_VBaseRangeMax: 276
|
||||
m_HAllowExceedBaseRangeMin: 1
|
||||
m_HAllowExceedBaseRangeMax: 1
|
||||
m_VAllowExceedBaseRangeMin: 1
|
||||
@ -785,29 +712,29 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 21
|
||||
width: 963
|
||||
height: 666
|
||||
width: 1037
|
||||
height: 552
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Translation: {x: 481.5, y: 333}
|
||||
m_Translation: {x: 518.5, y: 276}
|
||||
m_MarginLeft: 0
|
||||
m_MarginRight: 0
|
||||
m_MarginTop: 0
|
||||
m_MarginBottom: 0
|
||||
m_LastShownAreaInsideMargins:
|
||||
serializedVersion: 2
|
||||
x: -481.5
|
||||
y: -333
|
||||
width: 963
|
||||
height: 666
|
||||
x: -518.5
|
||||
y: -276
|
||||
width: 1037
|
||||
height: 552
|
||||
m_MinimalGUI: 1
|
||||
m_defaultScale: 1
|
||||
m_LastWindowPixelSize: {x: 963, y: 687}
|
||||
m_LastWindowPixelSize: {x: 1037, y: 573}
|
||||
m_ClearInEditMode: 1
|
||||
m_NoCameraWarning: 1
|
||||
m_LowResolutionForAspectRatios: 01000000000000000000
|
||||
m_XRRenderMode: 0
|
||||
m_RenderTexture: {fileID: 0}
|
||||
--- !u!114 &18
|
||||
--- !u!114 &15
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -827,10 +754,10 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 535
|
||||
y: 713
|
||||
width: 608
|
||||
height: 177
|
||||
x: 0
|
||||
y: 613
|
||||
width: 1037
|
||||
height: 372
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
@ -848,22 +775,22 @@ MonoBehaviour:
|
||||
m_SkipHidden: 0
|
||||
m_SearchArea: 1
|
||||
m_Folders:
|
||||
- Assets/Scenes
|
||||
- Assets/Script/GameScript
|
||||
m_Globs: []
|
||||
m_OriginalText:
|
||||
m_ViewMode: 1
|
||||
m_StartGridSize: 16
|
||||
m_LastFolders:
|
||||
- Assets/Script/PlayMode
|
||||
- Assets/Script/GameScript
|
||||
m_LastFoldersGridSize: 16
|
||||
m_LastProjectPath: C:\Users\UCUNI\OneDrive\Unity\ML-Agents\Aimbot-ParallelEnv
|
||||
m_LockTracker:
|
||||
m_IsLocked: 0
|
||||
m_FolderTreeState:
|
||||
scrollPos: {x: 0, y: 0}
|
||||
m_SelectedIDs: 05ca9a3b
|
||||
m_LastClickedID: 1000000005
|
||||
m_ExpandedIDs: 000000004294000000ca9a3b
|
||||
scrollPos: {x: 0, y: 352}
|
||||
m_SelectedIDs: 7c970000
|
||||
m_LastClickedID: 38780
|
||||
m_ExpandedIDs: 000000005e97000060970000629700006497000066970000689700006a9700006c9700006e97000070970000729700007497000076970000789700007a9700007c9700007e970000d297000000ca9a3bffffff7f
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name:
|
||||
@ -879,7 +806,7 @@ MonoBehaviour:
|
||||
m_IsRenaming: 0
|
||||
m_OriginalEventType: 11
|
||||
m_IsRenamingFilename: 1
|
||||
m_ClientGUIView: {fileID: 11}
|
||||
m_ClientGUIView: {fileID: 8}
|
||||
m_SearchString:
|
||||
m_CreateAssetUtility:
|
||||
m_EndAction: {fileID: 0}
|
||||
@ -891,7 +818,7 @@ MonoBehaviour:
|
||||
scrollPos: {x: 0, y: 0}
|
||||
m_SelectedIDs:
|
||||
m_LastClickedID: 0
|
||||
m_ExpandedIDs: 0000000042940000
|
||||
m_ExpandedIDs: 000000005e97000060970000629700006497000066970000689700006a9700006c9700006e97000070970000729700007497000076970000789700007a9700007c9700007e970000
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name:
|
||||
@ -922,20 +849,20 @@ MonoBehaviour:
|
||||
m_ExpandedInstanceIDs: c62300008a5c000000000000
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name: Train
|
||||
m_OriginalName: Train
|
||||
m_Name:
|
||||
m_OriginalName:
|
||||
m_EditFieldRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 0
|
||||
height: 0
|
||||
m_UserData: 38084
|
||||
m_UserData: 0
|
||||
m_IsWaitingForDelay: 0
|
||||
m_IsRenaming: 0
|
||||
m_OriginalEventType: 0
|
||||
m_OriginalEventType: 11
|
||||
m_IsRenamingFilename: 1
|
||||
m_ClientGUIView: {fileID: 11}
|
||||
m_ClientGUIView: {fileID: 8}
|
||||
m_CreateAssetUtility:
|
||||
m_EndAction: {fileID: 0}
|
||||
m_InstanceID: 0
|
||||
@ -947,7 +874,7 @@ MonoBehaviour:
|
||||
m_GridSize: 16
|
||||
m_SkipHiddenPackages: 0
|
||||
m_DirectoriesAreaWidth: 355
|
||||
--- !u!114 &19
|
||||
--- !u!114 &16
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -967,15 +894,15 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 64
|
||||
y: 780
|
||||
width: 961
|
||||
height: 259
|
||||
x: 65
|
||||
y: 667
|
||||
width: 1041
|
||||
height: 372
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
m_SaveData: []
|
||||
--- !u!114 &20
|
||||
--- !u!114 &17
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -995,10 +922,10 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 1144
|
||||
y: 212
|
||||
width: 334
|
||||
height: 371
|
||||
x: 1017
|
||||
y: 158
|
||||
width: 403
|
||||
height: 590
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
@ -1006,9 +933,9 @@ MonoBehaviour:
|
||||
m_SceneHierarchy:
|
||||
m_TreeViewState:
|
||||
scrollPos: {x: 0, y: 0}
|
||||
m_SelectedIDs: 5ef40000
|
||||
m_LastClickedID: 62558
|
||||
m_ExpandedIDs: 9aebffff80ecffff2aeeffff2aefffff60f2ffff22f3ffff72f5ffffbaf5ffffdaf5ffff32fbffff86f50000
|
||||
m_SelectedIDs: 30740000
|
||||
m_LastClickedID: 29744
|
||||
m_ExpandedIDs: 32fbffffea73000064740000187900003e7b0000047c0000
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name:
|
||||
@ -1024,7 +951,7 @@ MonoBehaviour:
|
||||
m_IsRenaming: 0
|
||||
m_OriginalEventType: 11
|
||||
m_IsRenamingFilename: 0
|
||||
m_ClientGUIView: {fileID: 13}
|
||||
m_ClientGUIView: {fileID: 10}
|
||||
m_SearchString:
|
||||
m_ExpandedScenes: []
|
||||
m_CurrenRootInstanceID: 0
|
||||
@ -1032,7 +959,7 @@ MonoBehaviour:
|
||||
m_IsLocked: 0
|
||||
m_CurrentSortingName: TransformSorting
|
||||
m_WindowGUID: 4c969a2b90040154d917609493e03593
|
||||
--- !u!114 &21
|
||||
--- !u!114 &18
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -1052,15 +979,15 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 1144
|
||||
y: 604
|
||||
width: 334
|
||||
height: 286
|
||||
x: 1017
|
||||
y: 769
|
||||
width: 403
|
||||
height: 355
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
m_SaveData: []
|
||||
--- !u!114 &22
|
||||
--- !u!114 &19
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -1072,7 +999,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 6c262c1329a02fa49b5cb4c297106f3f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_MinSize: {x: 129, y: 28}
|
||||
m_MinSize: {x: 136, y: 30}
|
||||
m_MaxSize: {x: 4000, y: 4000}
|
||||
m_TitleContent:
|
||||
m_Text: ProBuilder
|
||||
@ -1088,7 +1015,7 @@ MonoBehaviour:
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
m_SaveData: []
|
||||
--- !u!114 &23
|
||||
--- !u!114 &20
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -1108,10 +1035,10 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 1480
|
||||
y: 212
|
||||
width: 229
|
||||
height: 678
|
||||
x: 1422
|
||||
y: 158
|
||||
width: 411
|
||||
height: 966
|
||||
m_ViewDataDictionary: {fileID: 0}
|
||||
m_OverlayCanvas:
|
||||
m_LastAppliedPresetName: Default
|
||||
@ -1123,7 +1050,7 @@ MonoBehaviour:
|
||||
m_ControlHash: -371814159
|
||||
m_PrefName: Preview_InspectorPreview
|
||||
m_LastInspectedObjectInstanceID: -1
|
||||
m_LastVerticalScrollValue: 0
|
||||
m_LastVerticalScrollValue: 280
|
||||
m_GlobalObjectId:
|
||||
m_InspectorMode: 0
|
||||
m_LockTracker:
|
||||
|
Loading…
Reference in New Issue
Block a user