Roll a Ball & Battle City
这是以前做过的两个小游戏,是根据unity官方教程来学习的,非常的简单。github下载地址在文末。
Roll a Ball:
控制一个球来回移动,碰撞旋转的cube可以消除,颜色可以根据自己的喜好来设定,Roll a Ball其实也不算个游戏,没有音效,只有简单的字体UI。不过camera可以随着球体的移动而移动。下面是截图。
Battle City:
双人游戏,W/S/A/D/J控制player1,UP/DOWN/LEFT/RIGHT/ENTER控制player2。值得说的是,坦克在移动时尾部会有灰尘效果,而坦克发射炮弹时,上面有点光源,且炮弹落到地面有炸裂效果,炸裂效果是由几张贴图生成的。炮弹对于对方坦克具有物理击飞效果。Battle City具有背景音效,炮弹音效等等,也具有文字UI。
Roll a Ball:
1 using UnityEngine; 2 using System.Collections; 3 4 public class CameraController : MonoBehaviour { 5 6 public GameObject player; 7 8 private Vector3 offset; 9 10 // Use this for initialization 11 void Start () { 12 offset = transform.position - player.transform.position; 13 } 14 15 // Update is called once per frame 16 void LateUpdate () { 17 transform.position = player.transform.position + offset; 18 } 19 }
1 using UnityEngine; 2 using UnityEngine.UI; 3 using System.Collections; 4 5 public class PlayerController : MonoBehaviour 6 { 7 8 public float speed; 9 public Text countText; 10 public Text winText; 11 12 private Rigidbody rb; 13 14 private int count; 15 16 void Start() 17 { 18 rb = GetComponent<Rigidbody>(); 19 count = 0; 20 SetCountText(); 21 winText.text = ""; 22 } 23 24 void FixedUpdate() 25 { 26 float moveHorizontal = Input.GetAxis("Horizontal"); 27 float moveVertical = Input.GetAxis("Vertical"); 28 29 Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); 30 31 rb.AddForce(movement * speed); 32 } 33 34 void OnTriggerEnter(Collider other) 35 { 36 if (other.gameObject.CompareTag("Pick up")) 37 { 38 other.gameObject.SetActive(false); 39 count = count + 1; 40 SetCountText(); 41 } 42 } 43 44 void SetCountText() 45 { 46 countText.text = "Count: " + count.ToString(); 47 if (count >= 16) 48 { 49 winText.text = "You Win!"; 50 } 51 } 52 }
1 using UnityEngine; 2 using System.Collections; 3 4 public class Rotator : MonoBehaviour { 5 6 // Update is called once per frame 7 void Update () { 8 transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime); 9 } 10 }
Battle City:
- Camera
1 using UnityEngine; 2 3 public class CameraControl : MonoBehaviour 4 { 5 public float m_DampTime = 0.2f; 6 public float m_ScreenEdgeBuffer = 4f; 7 public float m_MinSize = 6.5f; 8 [HideInInspector] public Transform[] m_Targets; 9 10 11 private Camera m_Camera; 12 private float m_ZoomSpeed; 13 private Vector3 m_MoveVelocity; 14 private Vector3 m_DesiredPosition; 15 16 17 private void Awake() 18 { 19 m_Camera = GetComponentInChildren<Camera>(); 20 } 21 22 23 private void FixedUpdate() 24 { 25 Move(); 26 Zoom(); 27 } 28 29 30 private void Move() 31 { 32 FindAveragePosition(); 33 34 transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime); 35 } 36 37 38 private void FindAveragePosition() 39 { 40 Vector3 averagePos = new Vector3(); 41 int numTargets = 0; 42 43 for (int i = 0; i < m_Targets.Length; i++) 44 { 45 if (!m_Targets[i].gameObject.activeSelf) 46 continue; 47 48 averagePos += m_Targets[i].position; 49 numTargets++; 50 } 51 52 if (numTargets > 0) 53 averagePos /= numTargets; 54 55 averagePos.y = transform.position.y; 56 57 m_DesiredPosition = averagePos; 58 } 59 60 61 private void Zoom() 62 { 63 float requiredSize = FindRequiredSize(); 64 m_Camera.orthographicSize = Mathf.SmoothDamp(m_Camera.orthographicSize, requiredSize, ref m_ZoomSpeed, m_DampTime); 65 } 66 67 68 private float FindRequiredSize() 69 { 70 Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition); 71 72 float size = 0f; 73 74 for (int i = 0; i < m_Targets.Length; i++) 75 { 76 if (!m_Targets[i].gameObject.activeSelf) 77 continue; 78 79 Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position); 80 81 Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos; 82 83 size = Mathf.Max (size, Mathf.Abs (desiredPosToTarget.y)); 84 85 size = Mathf.Max (size, Mathf.Abs (desiredPosToTarget.x) / m_Camera.aspect); 86 } 87 88 size += m_ScreenEdgeBuffer; 89 90 size = Mathf.Max(size, m_MinSize); 91 92 return size; 93 } 94 95 96 public void SetStartPositionAndSize() 97 { 98 FindAveragePosition(); 99 100 transform.position = m_DesiredPosition; 101 102 m_Camera.orthographicSize = FindRequiredSize(); 103 } 104 }
- Managers
1 using UnityEngine; 2 using System.Collections; 3 //using UnityEngine.SceneManagement; 4 using UnityEngine.UI; 5 6 public class GameManager : MonoBehaviour 7 { 8 public int m_NumRoundsToWin = 5; 9 public float m_StartDelay = 3f; 10 public float m_EndDelay = 3f; 11 public CameraControl m_CameraControl; 12 public Text m_MessageText; 13 public GameObject m_TankPrefab; 14 public TankManager[] m_Tanks; 15 16 17 private int m_RoundNumber; 18 private WaitForSeconds m_StartWait; 19 private WaitForSeconds m_EndWait; 20 /* private TankManager m_RoundWinner; 21 private TankManager m_GameWinner; 22 */ 23 24 private void Start() 25 { 26 m_StartWait = new WaitForSeconds(m_StartDelay); 27 m_EndWait = new WaitForSeconds(m_EndDelay); 28 29 SpawnAllTanks(); 30 SetCameraTargets(); 31 32 StartCoroutine(GameLoop()); 33 } 34 35 36 private void SpawnAllTanks() 37 { 38 for (int i = 0; i < m_Tanks.Length; i++) 39 { 40 m_Tanks[i].m_Instance = 41 Instantiate(m_TankPrefab, m_Tanks[i].m_SpawnPoint.position, m_Tanks[i].m_SpawnPoint.rotation) as GameObject; 42 m_Tanks[i].m_PlayerNumber = i + 1; 43 m_Tanks[i].Setup(); 44 } 45 } 46 47 48 private void SetCameraTargets() 49 { 50 Transform[] targets = new Transform[m_Tanks.Length]; 51 52 for (int i = 0; i < targets.Length; i++) 53 { 54 targets[i] = m_Tanks[i].m_Instance.transform; 55 } 56 57 m_CameraControl.m_Targets = targets; 58 } 59 60 61 private IEnumerator GameLoop() 62 { 63 yield return StartCoroutine(RoundStarting()); 64 yield return StartCoroutine(RoundPlaying()); 65 yield return StartCoroutine(RoundEnding()); 66 67 /* if (m_GameWinner != null) 68 { 69 SceneManager.LoadScene(0); 70 } 71 else 72 { 73 StartCoroutine(GameLoop()); 74 } 75 */ } 76 77 78 private IEnumerator RoundStarting() 79 { 80 yield return m_StartWait; 81 } 82 83 84 private IEnumerator RoundPlaying() 85 { 86 yield return null; 87 } 88 89 90 private IEnumerator RoundEnding() 91 { 92 yield return m_EndWait; 93 } 94 95 96 private bool OneTankLeft() 97 { 98 int numTanksLeft = 0; 99 100 for (int i = 0; i < m_Tanks.Length; i++) 101 { 102 if (m_Tanks[i].m_Instance.activeSelf) 103 numTanksLeft++; 104 } 105 106 return numTanksLeft <= 1; 107 } 108 109 /* 110 private TankManager GetRoundWinner() 111 { 112 for (int i = 0; i < m_Tanks.Length; i++) 113 { 114 if (m_Tanks[i].m_Instance.activeSelf) 115 return m_Tanks[i]; 116 } 117 118 return null; 119 } 120 121 122 private TankManager GetGameWinner() 123 { 124 for (int i = 0; i < m_Tanks.Length; i++) 125 { 126 if (m_Tanks[i].m_Wins == m_NumRoundsToWin) 127 return m_Tanks[i]; 128 } 129 130 return null; 131 } 132 133 134 private string EndMessage() 135 { 136 string message = "DRAW!"; 137 138 if (m_RoundWinner != null) 139 message = m_RoundWinner.m_ColoredPlayerText + " WINS THE ROUND!"; 140 141 message += "\n\n\n\n"; 142 143 for (int i = 0; i < m_Tanks.Length; i++) 144 { 145 message += m_Tanks[i].m_ColoredPlayerText + ": " + m_Tanks[i].m_Wins + " WINS\n"; 146 } 147 148 if (m_GameWinner != null) 149 message = m_GameWinner.m_ColoredPlayerText + " WINS THE GAME!"; 150 151 return message; 152 } 153 */ 154 155 private void ResetAllTanks() 156 { 157 for (int i = 0; i < m_Tanks.Length; i++) 158 { 159 m_Tanks[i].Reset(); 160 } 161 } 162 163 164 private void EnableTankControl() 165 { 166 for (int i = 0; i < m_Tanks.Length; i++) 167 { 168 m_Tanks[i].EnableControl(); 169 } 170 } 171 172 173 private void DisableTankControl() 174 { 175 for (int i = 0; i < m_Tanks.Length; i++) 176 { 177 m_Tanks[i].DisableControl(); 178 } 179 } 180 }
1 using System; 2 using UnityEngine; 3 4 [Serializable] 5 public class TankManager 6 { 7 public Color m_PlayerColor; 8 public Transform m_SpawnPoint; 9 [HideInInspector] public int m_PlayerNumber; 10 [HideInInspector] public string m_ColoredPlayerText; 11 [HideInInspector] public GameObject m_Instance; 12 [HideInInspector] public int m_Wins; 13 14 15 private TankMovement m_Movement; 16 private TankShooting m_Shooting; 17 private GameObject m_CanvasGameObject; 18 19 20 public void Setup() 21 { 22 m_Movement = m_Instance.GetComponent<TankMovement>(); 23 m_Shooting = m_Instance.GetComponent<TankShooting>(); 24 m_CanvasGameObject = m_Instance.GetComponentInChildren<Canvas>().gameObject; 25 26 m_Movement.m_PlayerNumber = m_PlayerNumber; 27 m_Shooting.m_PlayerNumber = m_PlayerNumber; 28 29 m_ColoredPlayerText = "<color=#" + ColorUtility.ToHtmlStringRGB(m_PlayerColor) + ">PLAYER " + m_PlayerNumber + "</color>"; 30 31 MeshRenderer[] renderers = m_Instance.GetComponentsInChildren<MeshRenderer>(); 32 33 for (int i = 0; i < renderers.Length; i++) 34 { 35 renderers[i].material.color = m_PlayerColor; 36 } 37 } 38 39 40 public void DisableControl() 41 { 42 m_Movement.enabled = false; 43 m_Shooting.enabled = false; 44 45 m_CanvasGameObject.SetActive(false); 46 } 47 48 49 public void EnableControl() 50 { 51 m_Movement.enabled = true; 52 m_Shooting.enabled = true; 53 54 m_CanvasGameObject.SetActive(true); 55 } 56 57 58 public void Reset() 59 { 60 m_Instance.transform.position = m_SpawnPoint.position; 61 m_Instance.transform.rotation = m_SpawnPoint.rotation; 62 63 m_Instance.SetActive(false); 64 m_Instance.SetActive(true); 65 } 66 }
- Shell
1 using UnityEngine; 2 3 public class ShellExplosion : MonoBehaviour 4 { 5 public LayerMask m_TankMask; 6 public ParticleSystem m_ExplosionParticles; 7 public AudioSource m_ExplosionAudio; 8 public float m_MaxDamage = 100f; 9 public float m_ExplosionForce = 1000f; 10 public float m_MaxLifeTime = 2f; 11 public float m_ExplosionRadius = 5f; 12 13 14 private void Start() 15 { 16 Destroy(gameObject, m_MaxLifeTime); 17 } 18 19 20 private void OnTriggerEnter(Collider other) 21 { 22 // Find all the tanks in an area around the shell and damage them. 23 Collider[] colliders = Physics.OverlapSphere(transform.position, m_ExplosionRadius, m_TankMask); 24 for (int i = 0; i < colliders.Length; i++) 25 { 26 Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody>(); 27 28 if (!targetRigidbody) 29 continue; 30 31 targetRigidbody.AddExplosionForce(m_ExplosionForce, transform.position, m_ExplosionRadius); 32 TankHealth targetHealth = targetRigidbody.GetComponent<TankHealth>(); 33 34 if (!targetHealth) 35 continue; 36 37 float damage = CalculateDamage(targetRigidbody.position); 38 39 targetHealth.TakeDamage(damage); 40 } 41 42 m_ExplosionParticles.transform.parent = null; 43 44 m_ExplosionParticles.Play(); 45 46 m_ExplosionAudio.Play(); 47 48 Destroy(m_ExplosionParticles.gameObject, m_ExplosionParticles.duration); 49 Destroy(gameObject); 50 } 51 52 53 private float CalculateDamage(Vector3 targetPosition) 54 { 55 // Calculate the amount of damage a target should take based on it's position. 56 Vector3 explosionToTarget = targetPosition - transform.position; 57 58 float explosionDistance = explosionToTarget.magnitude; 59 60 float relativeDistance = (m_ExplosionRadius - explosionDistance) / m_ExplosionRadius; 61 62 float damage = relativeDistance * m_MaxDamage; 63 64 damage = Mathf.Max(0f, damage); 65 66 return damage; 67 } 68 }
- UI
1 using UnityEngine; 2 3 public class UIDirectionControl : MonoBehaviour 4 { 5 public bool m_UseRelativeRotation = true; 6 7 8 private Quaternion m_RelativeRotation; 9 10 11 private void Start() 12 { 13 m_RelativeRotation = transform.parent.localRotation; 14 } 15 16 17 private void Update() 18 { 19 if (m_UseRelativeRotation) 20 transform.rotation = m_RelativeRotation; 21 } 22 }
- UITank
1 using UnityEngine; 2 using UnityEngine.UI; 3 4 public class TankHealth : MonoBehaviour 5 { 6 public float m_StartingHealth = 100f; 7 public Slider m_Slider; 8 public Image m_FillImage; 9 public Color m_FullHealthColor = Color.green; 10 public Color m_ZeroHealthColor = Color.red; 11 public GameObject m_ExplosionPrefab; 12 13 /* 14 private AudioSource m_ExplosionAudio; 15 private ParticleSystem m_ExplosionParticles; 16 private float m_CurrentHealth; 17 private bool m_Dead; 18 19 20 private void Awake() 21 { 22 m_ExplosionParticles = Instantiate(m_ExplosionPrefab).GetComponent<ParticleSystem>(); 23 m_ExplosionAudio = m_ExplosionParticles.GetComponent<AudioSource>(); 24 25 m_ExplosionParticles.gameObject.SetActive(false); 26 } 27 28 29 private void OnEnable() 30 { 31 m_CurrentHealth = m_StartingHealth; 32 m_Dead = false; 33 34 SetHealthUI(); 35 } 36 */ 37 38 public void TakeDamage(float amount) 39 { 40 // Adjust the tank's current health, update the UI based on the new health and check whether or not the tank is dead. 41 } 42 43 44 private void SetHealthUI() 45 { 46 // Adjust the value and colour of the slider. 47 } 48 49 50 private void OnDeath() 51 { 52 // Play the effects for the death of the tank and deactivate it. 53 } 54 }
1 using UnityEngine; 2 3 public class TankMovement : MonoBehaviour 4 { 5 public int m_PlayerNumber = 1; 6 public float m_Speed = 12f; 7 public float m_TurnSpeed = 180f; 8 public AudioSource m_MovementAudio; 9 public AudioClip m_EngineIdling; 10 public AudioClip m_EngineDriving; 11 public float m_PitchRange = 0.2f; 12 13 /* 14 private string m_MovementAxisName; 15 private string m_TurnAxisName; 16 private Rigidbody m_Rigidbody; 17 private float m_MovementInputValue; 18 private float m_TurnInputValue; 19 private float m_OriginalPitch; 20 21 22 private void Awake() 23 { 24 m_Rigidbody = GetComponent<Rigidbody>(); 25 } 26 27 28 private void OnEnable () 29 { 30 m_Rigidbody.isKinematic = false; 31 m_MovementInputValue = 0f; 32 m_TurnInputValue = 0f; 33 } 34 35 36 private void OnDisable () 37 { 38 m_Rigidbody.isKinematic = true; 39 } 40 41 42 private void Start() 43 { 44 m_MovementAxisName = "Vertical" + m_PlayerNumber; 45 m_TurnAxisName = "Horizontal" + m_PlayerNumber; 46 47 m_OriginalPitch = m_MovementAudio.pitch; 48 } 49 */ 50 51 private void Update() 52 { 53 // Store the player's input and make sure the audio for the engine is playing. 54 } 55 56 57 private void EngineAudio() 58 { 59 // Play the correct audio clip based on whether or not the tank is moving and what audio is currently playing. 60 } 61 62 63 private void FixedUpdate() 64 { 65 // Move and turn the tank. 66 } 67 68 69 private void Move() 70 { 71 // Adjust the position of the tank based on the player's input. 72 } 73 74 75 private void Turn() 76 { 77 // Adjust the rotation of the tank based on the player's input. 78 } 79 }
1 using UnityEngine; 2 using UnityEngine.UI; 3 4 public class TankShooting : MonoBehaviour 5 { 6 public int m_PlayerNumber = 1; 7 public Rigidbody m_Shell; 8 public Transform m_FireTransform; 9 public Slider m_AimSlider; 10 public AudioSource m_ShootingAudio; 11 public AudioClip m_ChargingClip; 12 public AudioClip m_FireClip; 13 public float m_MinLaunchForce = 15f; 14 public float m_MaxLaunchForce = 30f; 15 public float m_MaxChargeTime = 0.75f; 16 17 /* 18 private string m_FireButton; 19 private float m_CurrentLaunchForce; 20 private float m_ChargeSpeed; 21 private bool m_Fired; 22 23 24 private void OnEnable() 25 { 26 m_CurrentLaunchForce = m_MinLaunchForce; 27 m_AimSlider.value = m_MinLaunchForce; 28 } 29 30 31 private void Start() 32 { 33 m_FireButton = "Fire" + m_PlayerNumber; 34 35 m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime; 36 } 37 */ 38 39 private void Update() 40 { 41 // Track the current state of the fire button and make decisions based on the current launch force. 42 } 43 44 45 private void Fire() 46 { 47 // Instantiate and launch the shell. 48 } 49 }