浏览代码

add more controllers and ball spawner

/hh-develop-water-balloon-fight
HH 4 年前
当前提交
8ae5b16b
共有 16 个文件被更改,包括 715 次插入5 次删除
  1. 2
      Project/Assets/ML-Agents/Examples/FPS_Game/Input/FPSAgentInput.cs
  2. 4
      Project/Assets/ML-Agents/Examples/FPS_Game/Prefabs/Projectile - BALL.prefab
  3. 18
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/FPSAgent.cs
  4. 2
      Project/Assets/Particle Examples/EffectExamples/Water Effects/Prefabs/BigSplash.prefab
  5. 2
      Project/Packages/manifest.json
  6. 2
      Project/Packages/packages-lock.json
  7. 1
      Project/ProjectSettings/TagManager.asset
  8. 34
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBall.cs
  9. 11
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBall.cs.meta
  10. 336
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallAgent.cs
  11. 11
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallAgent.cs.meta
  12. 62
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallGameController.cs
  13. 11
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallGameController.cs.meta
  14. 213
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/ThrowBall.cs
  15. 11
      Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/ThrowBall.cs.meta

2
Project/Assets/ML-Agents/Examples/FPS_Game/Input/FPSAgentInput.cs


}
}
public bool shootPressed;
// Update is called once per frame
void FixedUpdate()
{

}
moveInput = actionMap.Walk.ReadValue<Vector2>();
shootInput = actionMap.Shoot.ReadValue<float>() > 0;
shootPressed = actionMap.Shoot.triggered;
// shootInput = gamepad.rightTrigger.isPressed;
shieldInput = actionMap.Shield.ReadValue<float>() > 0;
// rotateInput = actionMap.RotateBody.ReadValue<Vector2>();

4
Project/Assets/ML-Agents/Examples/FPS_Game/Prefabs/Projectile - BALL.prefab


- component: {fileID: 4341296992446652170}
m_Layer: 10
m_Name: Projectile - BALL
m_TagString: projectile
m_TagString: dodgeBall
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0

- component: {fileID: 4977931146242317046}
m_Layer: 10
m_Name: Sphere
m_TagString: Untagged
m_TagString: dodgeBall
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0

18
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/FPSAgent.cs


using System;
using System.Collections;
using System.Collections.Generic;
using MLAgents;

using Unity.MLAgents.Sensors;
using UnityEngine.InputSystem;
using Random = UnityEngine.Random;
public class FPSAgent : Agent
{

[Header("SHIELD")] public ShieldController AgentShield;
public FPSAgentInput input;
private DodgeBallGameController m_GameController;
// Start is called before the first frame update
public override void Initialize()
{

input = GetComponent<FPSAgentInput>();
m_GameController = FindObjectOfType<DodgeBallGameController>();
}
public override void OnEpisodeBegin()

print("cancelled" + Time.frameCount + m_ShootInput);
}
}
private void OnCollisionEnter(Collision col)
{
if (col.transform.CompareTag("dodgeBall"))
{
}
}
public override void Heuristic(in ActionBuffers actionsOut)
{

2
Project/Assets/Particle Examples/EffectExamples/Water Effects/Prefabs/BigSplash.prefab


m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1722726733478836}
m_LocalRotation: {x: -0.0000020191073, y: -0.7071068, z: -0.7071068, w: 0.0000020191073}
m_LocalPosition: {x: -3.593756, y: 1.0010649, z: 11.646745}
m_LocalPosition: {x: 5.4949994, y: 1.001243, z: 1.929068}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 4375671181544448}

2
Project/Packages/manifest.json


"com.unity.collab-proxy": "1.2.16",
"com.unity.ide.rider": "3.0.3",
"com.unity.ide.vscode": "1.2.3",
"com.unity.inputsystem": "1.0.1",
"com.unity.inputsystem": "1.0.2",
"com.unity.ml-agents": "file:../../com.unity.ml-agents",
"com.unity.ml-agents.extensions": "file:../../com.unity.ml-agents.extensions",
"com.unity.multiplayer-hlapi": "1.0.6",

2
Project/Packages/packages-lock.json


"url": "https://packages.unity.com"
},
"com.unity.inputsystem": {
"version": "1.0.1",
"version": "1.0.2",
"depth": 0,
"source": "registry",
"dependencies": {},

1
Project/ProjectSettings/TagManager.asset


- purpleAgent
- purpleGoal
- projectile
- dodgeBall
layers:
- Default
- TransparentFX

34
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBall.cs


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DodgeBall : MonoBehaviour
{
public bool inPlay;
// Start is called before the first frame update
void Start()
{
}
private void OnEnable()
{
inPlay = true;
}
// Update is called once per frame
void Update()
{
}
private void OnCollisionEnter(Collision other)
{
//IF NOT MY TEAM
//PLAYER GOES TO TIMEOUT
}
}

11
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBall.cs.meta


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

336
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallAgent.cs


using System;
using System.Collections;
using System.Collections.Generic;
using MLAgents;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
using Random = UnityEngine.Random;
public class DodgeBallAgent : Agent
{
[Header("TEAM")]
public int teamID;
private AgentCubeMovement m_CubeMovement;
public ThrowBall ThrowController;
[Header("HEALTH")] public AgentHealth AgentHealth;
[Header("SHIELD")] public ShieldController AgentShield;
[Header("INPUT")]
public FPSAgentInput input;
[Header("INVENTORY")]
public int currentNumberOfBalls;
public List<DodgeBall> currentlyHeldBalls;
public bool UseVectorObs;
private DodgeBallGameController m_GameController;
private Rigidbody m_AgentRb;
public List<Transform> ActiveBallsList = new List<Transform>();
// Start is called before the first frame update
public override void Initialize()
{
m_CubeMovement = GetComponent<AgentCubeMovement>();
// m_Cam = Camera.main;
m_AgentRb = GetComponent<Rigidbody>();
input = GetComponent<FPSAgentInput>();
}
public override void OnEpisodeBegin()
{
m_CubeMovement = GetComponent<AgentCubeMovement>();
// m_Cam = Camera.main;
m_AgentRb = GetComponent<Rigidbody>();
input = GetComponent<FPSAgentInput>();
m_GameController = FindObjectOfType<DodgeBallGameController>();
// Unfreeze();
// Unpoison();
// Unsatiate();
// m_Shoot = false;
// m_AgentRb.velocity = Vector3.zero;
// myLaser.transform.localScale = new Vector3(0f, 0f, 0f);
// transform.position = new Vector3(Random.Range(-m_MyArea.range, m_MyArea.range),
// 2f, Random.Range(-m_MyArea.range, m_MyArea.range))
// + area.transform.position;
transform.rotation = Quaternion.Euler(new Vector3(0f, Random.Range(0, 360)));
SetActiveBalls(0);
// SetResetParameters();
}
void SetActiveBalls(int numOfBalls)
{
int i = 0;
foreach (var item in ActiveBallsList)
{
var active = i < numOfBalls;
ActiveBallsList[i].gameObject.SetActive(active);
i++;
}
// for (int i = 0; i < numOfBalls; i++)
// {
// var active = i < numOfBalls;
// ActiveBallsList[i].gameObject.SetActive();
// }
}
public override void CollectObservations(VectorSensor sensor)
{
if (UseVectorObs)
{
// var localVelocity = transform.InverseTransformDirection(m_AgentRb.velocity);
// sensor.AddObservation(localVelocity.x);
// sensor.AddObservation(localVelocity.z);
// sensor.AddObservation(m_Frozen);
// sensor.AddObservation(m_ShootInput);
}
// else if (useVectorFrozenFlag)
// {
// sensor.AddObservation(m_Frozen);
// }
}
public void MoveAgent(ActionSegment<float> act)
{
// if (!m_Frozen)
// {
// var shootCommand = false;
// var forwardAxis = act[0];
// var rightAxis = act[1];
// var rotateAxis = act[2];
// var shootAxis = act[3];
// m_Shoot = shootAxis > 0;
// m_CubeMovement.RotateBody(rotateAxis, forwardAxis);
// m_CubeMovement.RunOnGround(m_AgentRb, m_Cam.transform.TransformDirection(new Vector3(0, 0, forwardAxis)));
// m_CubeMovement.Strafe(transform.right * rightAxis);
if (AgentHealth.Dead)
{
return;
}
m_InputV = act[0];
m_InputH = act[1];
m_Rotate = act[2];
m_ShootInput = act[3];
// m_CubeMovement.RotateBody(m_Rotate, m_InputV);
m_CubeMovement.Look(m_Rotate);
Vector3 moveDir = input.Cam.transform.TransformDirection(new Vector3(m_InputH, 0, m_InputV));
moveDir.y = 0;
// m_CubeMovement.RunOnGround(m_AgentRb, m_Cam.transform.TransformDirection(new Vector3(0, 0, m_InputV)));
// m_CubeMovement.RunOnGround(m_AgentRb, moveDir);
m_CubeMovement.RunOnGround(moveDir);
// if (m_InputH != 0)
// {
// if (leftStrafe)
// {
// m_CubeMovement.Strafe(transform.right * -1);
// leftStrafe = false;
// }
// if (rightStrafe)
// {
// m_CubeMovement.Strafe(transform.right * 1);
// rightStrafe = false;
// }
//
// m_CubeMovement.Strafe(transform.right * m_InputH);
// }
if (AgentShield && act[6] > 0)
{
AgentShield.ActivateShield(true);
}
else
{
AgentShield.ActivateShield(false);
}
// if (m_ShootInput > 0 && currentNumberOfBalls > 0)
// {
// gunController.Shoot();
// currentNumberOfBalls--;
// }
if (input.shootPressed && currentNumberOfBalls > 0)
{
ThrowController.Shoot();
currentNumberOfBalls--;
}
if (act[4] > 0 && m_CubeMovement.groundCheck.isGrounded)
{
m_CubeMovement.Jump();
}
if (act[5] > 0)
{
m_CubeMovement.Dash(moveDir);
}
// }
if (m_AgentRb.velocity.sqrMagnitude > 25f) // slow it down
{
m_AgentRb.velocity *= 0.95f;
}
}
// void OnCollisionEnter(Collision col)
// {
// if (col.gameObject.CompareTag("projectile"))
// {
// //IMPLEMENT HEALTH MECHANIC
// }
// }
public override void OnActionReceived(ActionBuffers actionBuffers)
{
MoveAgent(actionBuffers.ContinuousActions);
}
public float m_InputH;
private float m_InputV;
private float m_Rotate;
public bool leftStrafe;
public bool rightStrafe;
void Update()
{
// m_InputH = Input.GetKeyDown(KeyCode.K) ? 1 : Input.GetKeyDown(KeyCode.J) ? -1 : 0; //inputH
if (Input.GetKeyDown(KeyCode.K))
{
rightStrafe = true;
}
if (Input.GetKeyDown(KeyCode.J))
{
leftStrafe = true;
}
}
// void FixedUpdate()
// {
// m_InputV = Input.GetKey(KeyCode.W) ? 1 : Input.GetKey(KeyCode.S) ? -1 : 0; //inputV
// // m_InputH = 0;
// // m_InputH += Input.GetKeyDown(KeyCode.Q) ? -1 : 0;
// // m_InputH += Input.GetKeyDown(KeyCode.E) ? 1 : 0;
// // m_InputH = Input.GetKeyDown(KeyCode.E) ? 1 : Input.GetKeyDown(KeyCode.Q) ? -1 : 0; //inputH
// m_Rotate = 0;
// m_Rotate += Input.GetKey(KeyCode.A) ? -1 : 0;
// m_Rotate += Input.GetKey(KeyCode.D) ? 1 : 0;
// // m_Rotate = Input.GetKey(KeyCode.D) ? 1 : Input.GetKey(KeyCode.A) ? -1 : 0; //rotate
// m_ShootInput = Input.GetKey(KeyCode.Space) ? 1 : 0; //shoot
// }
private Vector2 inputMovement;
private Vector2 rotateMovement;
public float m_ShootInput;
public void OnMovement(InputAction.CallbackContext value)
{
inputMovement = value.ReadValue<Vector2>();
}
public void OnRotate(InputAction.CallbackContext value)
{
rotateMovement = value.ReadValue<Vector2>();
}
public void OnShoot(InputAction.CallbackContext value)
{
// m_ShootInput = value.canceled? 0: value.ReadValue<float>();
// m_ShootInput = 0;
if (value.started)
{
print("started");
}
if (value.performed)
{
print("performed" + Time.frameCount);
}
if (!value.canceled)
{
print("not cancelled" + Time.frameCount + m_ShootInput);
m_ShootInput = value.ReadValue<float>();
// m_ShootInput = value.
}
else
{
m_ShootInput = 0;
print("cancelled" + Time.frameCount + m_ShootInput);
}
}
private void OnCollisionEnter(Collision col)
{
if (col.transform.CompareTag("dodgeBall"))
{
if (currentNumberOfBalls < 3)
{
currentNumberOfBalls++;
}
}
}
public override void Heuristic(in ActionBuffers actionsOut)
{
var contActionsOut = actionsOut.ContinuousActions;
// contActionsOut[0] = m_InputV; //inputV
// contActionsOut[2] = m_Rotate; //rotate
// contActionsOut[3] = m_ShootInput; //shoot
// contActionsOut[0] = Input.GetKey(KeyCode.W) ? 1 : Input.GetKey(KeyCode.S) ? -1 : 0; //inputV
// contActionsOut[1] = Input.GetKeyDown(KeyCode.E) ? 1 : Input.GetKeyDown(KeyCode.Q) ? -1 : 0; //inputH
// contActionsOut[2] = Input.GetKey(KeyCode.D) ? 1 : Input.GetKey(KeyCode.A) ? -1 : 0; //rotate
// contActionsOut[3] = Input.GetKey(KeyCode.Space) ? 1 : 0; //shoot
contActionsOut[0] = input.moveInput.y;
contActionsOut[1] = input.moveInput.x;
// contActionsOut[2] = input.rotateInput.x; //rotate
contActionsOut[2] = input.rotateInput.x; //rotate
contActionsOut[3] = input.shootInput ? 1 : 0; //shoot
contActionsOut[4] = input.CheckIfInputSinceLastFrame(ref input.jumpInput) ? 1 : 0; //jump
contActionsOut[5] = input.CheckIfInputSinceLastFrame(ref input.dashInput) ? 1 : 0; //jump
// contActionsOut[4] = input.jumpInput ? 1 : 0; //jump
// contActionsOut[5] = input.dashInput ? 1 : 0; //dash
contActionsOut[6] = input.shieldInput ? 1 : 0; //shield
if (input.jumpInput)
{
print($"Agent: Jump: {input.jumpInput} : {Time.frameCount}");
}
// contActionsOut[0] = inputMovement.y;
// contActionsOut[1] = inputMovement.x;
// contActionsOut[2] = rotateMovement.x;
// m_InputH = 0;
// if (leftStrafe)
// {
// // print("leftstrafe");
// m_InputH += -1;
// leftStrafe = false;
// }
//
// if (rightStrafe)
// {
// // print("rightstrafe");
// m_InputH += 1;
// rightStrafe = false;
// }
//
// contActionsOut[1] = m_InputH; //inputH
}
}

11
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallAgent.cs.meta


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

62
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallGameController.cs


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class DodgeBallGameController : MonoBehaviour
{
[Header("PLAYERS")]
public Transform Team0SpawnPos;
public Transform Team1SpawnPos;
public int NumberOfPlayersOnTeam0 = 1;
public int NumberOfPlayersOnTeam1 = 1;
[Header("BALLS")] public GameObject BallPrefab;
public float BallSpawnRadius = 3;
public Transform BallSpawnPosition;
public int NumberOfBallsToSpawn = 10;
public int NumberOfBallsPlayersCanHold = 3;
[Serializable]
public class DodgeBallPlayer
{
public int teamID;
public int currentNumberOfBalls;
public FPSAgent agent;
public List<DodgeBall> currentlyHeldBalls;
}
void ResetScene()
{
for (int i = 0; i < NumberOfBallsToSpawn; i++)
{
GameObject g = Instantiate(BallPrefab, BallSpawnPosition.position + Random.insideUnitSphere * BallSpawnRadius,
Quaternion.identity);
g.SetActive(true);
}
}
public List<DodgeBallAgent> Team0Players;
public List<DodgeBallAgent> Team1Players;
public List<DodgeBall> dodgeBallsListTeamO;
public List<DodgeBall> dodgeBallsListTeam1;
public Dictionary<DodgeBallAgent, DodgeBallPlayer> PlayersDict = new Dictionary<DodgeBallAgent, DodgeBallPlayer>();
// Start is called before the first frame update
void Awake()
{
ResetScene();
}
// // Update is called once per frame
// void Update()
// {
//
// }
}

11
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/DodgeBallGameController.cs.meta


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

213
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/ThrowBall.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
[RequireComponent(typeof(AudioSource))]
public class ThrowBall : MonoBehaviour
{
public bool AllowKeyboardInput = true; //this mode ignores player input
public bool initialized; //has this robot been initialized
public KeyCode shootKey = KeyCode.J;
[Header("AUTOSHOOT")] public bool autoShootEnabled;
//SHOOTING RATE
[Header("SHOOTING RATE")]
public float shootingRate = .02f; //can shoot every shootingRate seconds. ex: .5 can shoot every .5 seconds
// private float shootTimer;
public bool coolDownWait;
//PROJECTILES
[Header("PROJECTILE")]
public GameObject projectilePrefab;
public int numberOfProjectilesToPool = 25;
public Transform projectileOrigin; //the transform the projectile will originate from
// public List<Projectile> projectilePoolList = new List<Projectile>(); //projectiles to shoot
public List<Rigidbody> projectilePoolList = new List<Rigidbody>(); //projectiles to shoot
//FORCES
[Header("FORCES")]
public float forceToUse;
[Header("MUZZLE FLASH")]
public bool UseMuzzleFlash;
public GameObject MuzzleFlashObject;
[Header("SOUND")]
public bool PlaySound;
public ForceMode forceMode;
public GunSFX GunSFX;
private AudioSource m_AudioSource;
[Header("SCREEN SHAKE")]
public bool UseScreenShake;
[Header("TRANSFORM SHAKE")] public bool ShakeTransform;
public float ShakeDuration = .1f;
public float ShakeAmount = .1f;
private Vector3 startPos;
private bool m_TransformIsShaking;
CinemachineImpulseSource impulseSource;
// Start is called before the first frame update
void Awake()
{
if (!initialized)
{
Initialize();
}
}
void OnEnable()
{
if (!initialized)
{
Initialize();
}
}
void Initialize()
{
projectilePoolList.Clear(); //clear list in case it's not empty
for (var i = 0; i < numberOfProjectilesToPool; i++)
{
impulseSource = GetComponent<CinemachineImpulseSource>();
GameObject obj = Instantiate(projectilePrefab, transform.position, Quaternion.identity);
Rigidbody p = obj.GetComponent<Rigidbody>();
projectilePoolList.Add(p);
p.transform.position = projectileOrigin.position;
// p.projectileController = this;
p.gameObject.SetActive(false);
}
if (MuzzleFlashObject)
{
MuzzleFlashObject.SetActive(false);
}
m_AudioSource = GetComponent<AudioSource>();
initialized = true;
}
void Update()
{
if (!AllowKeyboardInput)
{
return;
}
if (Input.GetKeyDown(shootKey))
{
Shoot();
// ShootQuantity(1);
}
}
// void FixedUpdate()
// {
// coolDownWait = shootTimer > shootingRate ? false : true;
// shootTimer += Time.fixedDeltaTime;
// if (autoShootEnabled)
// {
// Shoot();
// }
// }
// public void ShootQuantity(int num)
// {
// var i = 0;
// while (i < num)
// {
// //shoot first available projectile in the pool
// foreach (var item in projectilePoolList)
// {
// if (!item.gameObject.activeInHierarchy)
// {
// FireProjectile(item.rb);
// impulseSource.GenerateImpulse();
// break;
// }
// }
//
// i++;
// }
// }
public void Shoot()
{
if (coolDownWait || !gameObject.activeSelf)
{
return;
}
// shootTimer = 0; //reset timer
//shoot first available projectile in the pool
foreach (var item in projectilePoolList)
{
if (!item.gameObject.activeInHierarchy)
{
FireProjectile(item);
// FireProjectile(item.rb);
break;
}
}
}
public void FireProjectile(Rigidbody rb)
{
rb.transform.position = projectileOrigin.position;
rb.transform.rotation = projectileOrigin.rotation;
// rb.position = projectileOrigin.position;
// rb.rotation = projectileOrigin.rotation;
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
rb.gameObject.SetActive(true);
rb.AddForce(projectileOrigin.forward * forceToUse, forceMode);
if (UseScreenShake && impulseSource)
{
impulseSource.GenerateImpulse();
}
if (ShakeTransform && !m_TransformIsShaking)
{
StartCoroutine(I_ShakeTransform());
}
if (PlaySound)
{
m_AudioSource.PlayOneShot(m_AudioSource.clip);
// GunSFX.PlayAudio();
}
}
IEnumerator I_ShakeTransform()
{
m_TransformIsShaking = true;
WaitForFixedUpdate wait = new WaitForFixedUpdate();
if (UseMuzzleFlash && MuzzleFlashObject)
{
MuzzleFlashObject.transform.localScale = Random.Range(.5f, 1.5f) * Vector3.one;
MuzzleFlashObject.SetActive(true);
}
float timer = 0;
startPos = transform.localPosition;
while (timer < ShakeDuration)
{
var pos = startPos + (Random.insideUnitSphere * ShakeAmount);
transform.localPosition = pos;
timer += Time.fixedDeltaTime;
yield return wait;
}
transform.localPosition = startPos;
if (UseMuzzleFlash && MuzzleFlashObject)
{
MuzzleFlashObject.SetActive(false);
}
m_TransformIsShaking = false;
}
}

11
Project/Assets/ML-Agents/Examples/FPS_Game/Scripts/ThrowBall.cs.meta


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

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存