Bow & Arrow 学习
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEditor; /// <summary> /// 游戏控制 /// </summary> public class bowAndArrow : MonoBehaviour { /// <summary> /// Ray /// </summary> private Ray mouseRay1; /// <summary> /// RaycastHit /// </summary> private RaycastHit rayHit; /// <summary> /// 射线击中的x轴位置 /// </summary> private float posX; /// <summary> /// 射线击中的y轴位置 /// </summary> private float posY; /// <summary> /// 弓绳 /// </summary> public GameObject bowString; /// <summary> /// 箭 /// </summary> GameObject arrow; /// <summary> /// 箭预设 /// </summary> public GameObject arrowPrefab; /// <summary> /// 用来作为射出的箭的父物体 /// </summary> public GameObject gameManager; /// <summary> /// 伤害文本 /// </summary> public GameObject risingText; /// <summary> /// 目标 /// </summary> public GameObject target; /// <summary> /// 拉弓的声音 /// </summary> public AudioClip stringPull; /// <summary> /// 放箭的声音 /// </summary> public AudioClip stringRelease; /// <summary> /// 箭飞行的声音 /// </summary> public AudioClip arrowSwoosh; /// <summary> /// 拉弓的声音是否已播放 /// </summary> bool stringPullSoundPlayed; /// <summary> /// 放箭的声音是否已播放 /// </summary> bool stringReleaseSoundPlayed; /// <summary> /// 箭飞行的声音是否已播放 /// </summary> bool arrowSwooshSoundPlayed; /// <summary> /// 弓的位置 /// </summary> private List<Vector3> bowStringPosition; /// <summary> /// 弓的线条渲染器 /// </summary> LineRenderer bowStringLinerenderer; float arrowStartX; float length; /// <summary> /// 箭是否已射出 /// </summary> bool arrowShot; /// <summary> /// 箭是否准备好 /// </summary> bool arrowPrepared; // position of the line renderers middle part Vector3 stringPullout; Vector3 stringRestPosition = new Vector3 (-0.44f, -0.06f, 2f); /// <summary> /// 游戏状态 /// </summary> public enum GameStates { /// <summary> /// 目录 /// </summary> menu, /// <summary> /// 教程 /// </summary> instructions, /// <summary> /// 游戏中 /// </summary> game, /// <summary> /// 游戏结束 /// </summary> over, /// <summary> /// 最高分 /// </summary> hiscore, }; /// <summary> /// 游戏状态 /// </summary> public GameStates gameState = GameStates.menu; /// <summary> /// 目录面板 /// </summary> public Canvas menuCanvas; /// <summary> /// 指示面板 /// </summary> public Canvas instructionsCanvas; /// <summary> /// 最高分面板 /// </summary> public Canvas highscoreCanvas; /// <summary> /// 游戏面板 /// </summary> public Canvas gameCanvas; /// <summary> /// 游戏结束面板 /// </summary> public Canvas gameOverCanvas; /// <summary> /// 箭的数量文本 /// </summary> public Text arrowText; /// <summary> /// 得分文本 /// </summary> public Text scoreText; /// <summary> /// 最后得分文本 /// </summary> public Text endscoreText; /// <summary> /// 最高得分 /// </summary> public Text actualHighscoreText; /// <summary> /// 新的最高得分 /// </summary> public Text newHighscoreText; /// <summary> /// 新的最高得分提示文本 /// </summary> public Text newHighText; /// <summary> /// 每局能使用的箭数量 /// </summary> public int arrows = 20; /// <summary> /// 实际得分 /// </summary> public int score = 0; /// <summary> /// 重置游戏 /// </summary> void resetGame() { arrows = 20; score = 0; //如果没有找到arrow,创建新的arrow if (GameObject.Find("arrow") == null) createArrow (true); } void Start () { //设置ui显隐 menuCanvas.enabled = true; instructionsCanvas.enabled = false; highscoreCanvas.enabled = false; gameCanvas.enabled = false; gameOverCanvas.enabled = false; initScore (); createArrow (true); bowStringLinerenderer = bowString.AddComponent<LineRenderer>(); bowStringLinerenderer.SetVertexCount(3); bowStringLinerenderer.SetWidth(0.05F, 0.05F); bowStringLinerenderer.useWorldSpace = false; bowStringLinerenderer.material = Resources.Load ("Materials/bowStringMaterial") as Material; bowStringPosition = new List<Vector3> (); bowStringPosition.Add(new Vector3 (-0.44f, 1.43f, 2f)); bowStringPosition.Add(new Vector3 (-0.44f, -0.06f, 2f)); bowStringPosition.Add(new Vector3 (-0.43f, -1.32f, 2f)); bowStringLinerenderer.SetPosition (0, bowStringPosition [0]); bowStringLinerenderer.SetPosition (1, bowStringPosition [1]); bowStringLinerenderer.SetPosition (2, bowStringPosition [2]); arrowStartX = 0.7f; stringPullout = stringRestPosition; } void Update () { //检查游戏状态 switch (gameState) { //目录状态,按下esc 退出游戏 case GameStates.menu: if (Input.GetKeyDown(KeyCode.Escape)) { #if UNITY_EDITOR EditorApplication.isPlaying = false; #else Application.Quit(); #endif } break; case GameStates.game: showArrows(); showScore(); //按下esc 显示目录 if (Input.GetKeyDown(KeyCode.Escape)) { showMenu(); } //如果按下鼠标左键 if (Input.GetMouseButton(0)) { //播放拉弓的声音 if (!stringPullSoundPlayed) { GetComponent<AudioSource>().PlayOneShot(stringPull); stringPullSoundPlayed = true; } prepareArrow(); } //如果鼠标抬起且箭已准备就绪 if (Input.GetMouseButtonUp (0) && arrowPrepared) { //播放放箭的声音 if (!stringReleaseSoundPlayed) { GetComponent<AudioSource>().PlayOneShot(stringRelease); stringReleaseSoundPlayed = true; } //播放箭飞行的声音 if (!arrowSwooshSoundPlayed) { GetComponent<AudioSource>().PlayOneShot(arrowSwoosh); arrowSwooshSoundPlayed = true; } shootArrow(); } drawBowString(); break; case GameStates.instructions: break; case GameStates.over: break; case GameStates.hiscore: break; } } /// <summary> /// 初始化得分 /// </summary> public void initScore() { if (!PlayerPrefs.HasKey ("Score")) PlayerPrefs.SetInt ("Score", 0); } /// <summary> /// 显示得分 /// </summary> public void showScore() { scoreText.text = "Score: " + score.ToString(); } /// <summary> /// 显示箭数量 /// </summary> public void showArrows() { arrowText.text = "Arrows: " + arrows.ToString (); } /// <summary> /// 创建箭 /// </summary> /// <param name="hitTarget">是否击中目标</param> public void createArrow(bool hitTarget) { Camera.main.GetComponent<camMovement> ().resetCamera (); stringPullSoundPlayed = false; stringReleaseSoundPlayed = false; arrowSwooshSoundPlayed = false; //如果还有可使用的箭 if (arrows > 0) { //如果击中目标,随机设置目标的位置 if (hitTarget) { float x = Random.Range(-1f,8f); float y = Random.Range(-3f,3f); Vector3 position = target.transform.position; position.x = x; position.y = y; target.transform.position = position; } //创建一个新箭 this.transform.localRotation = Quaternion.identity; arrow = Instantiate (arrowPrefab, Vector3.zero, Quaternion.identity) as GameObject; arrow.name = "arrow"; arrow.transform.localScale = this.transform.localScale; arrow.transform.localPosition = this.transform.position + new Vector3 (0.7f, 0, 0); arrow.transform.localRotation = this.transform.localRotation; arrow.transform.parent = this.transform; arrow.GetComponent<rotateArrow> ().setBow (gameObject); arrowShot = false; arrowPrepared = false; arrows --; } else { gameState = GameStates.over; gameOverCanvas.enabled = true; endscoreText.text = "You shot all the arrows and scored " + score + " points."; } } /// <summary> /// 射箭 /// </summary> public void shootArrow() { if (arrow.GetComponent<Rigidbody>() == null) { arrowShot = true; arrow.AddComponent<Rigidbody>(); arrow.transform.parent = gameManager.transform; arrow.GetComponent<Rigidbody>().AddForce (Quaternion.Euler (new Vector3(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y,transform.rotation.eulerAngles.z))*new Vector3(25f*length,0,0), ForceMode.VelocityChange); } arrowPrepared = false; stringPullout = stringRestPosition; Camera.main.GetComponent<camMovement> ().resetCamera (); Camera.main.GetComponent<camMovement> ().setArrow (arrow); } /// <summary> /// 准备弓箭 /// </summary> public void prepareArrow() { mouseRay1 = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(mouseRay1, out rayHit, 1000f) && arrowShot == false) { posX = this.rayHit.point.x; posY = this.rayHit.point.y; Vector2 mousePos = new Vector2(transform.position.x-posX,transform.position.y-posY); float angleZ = Mathf.Atan2(mousePos.y,mousePos.x)*Mathf.Rad2Deg; transform.eulerAngles = new Vector3(0,0,angleZ); length = mousePos.magnitude / 3f; length = Mathf.Clamp(length,0,1); stringPullout = new Vector3(-(0.44f+length), -0.06f, 2f); Vector3 arrowPosition = arrow.transform.localPosition; arrowPosition.x = (arrowStartX - length); arrow.transform.localPosition = arrowPosition; } arrowPrepared = true; } /// <summary> /// 画弓绳 /// </summary> public void drawBowString() { bowStringLinerenderer = bowString.GetComponent<LineRenderer>(); bowStringLinerenderer.SetPosition (0, bowStringPosition [0]); bowStringLinerenderer.SetPosition (1, stringPullout); bowStringLinerenderer.SetPosition (2, bowStringPosition [2]); } /// <summary> /// 设置得分 /// </summary> /// <param name="points">分数</param> public void setPoints(int points){ score += points; //如果得分是50 if (points == 50) { //加一可用弓数量 arrows++; //创建提示文本 GameObject rt1 = (GameObject)Instantiate(risingText, new Vector3(0,0,0),Quaternion.identity); rt1.transform.position = this.transform.position + new Vector3(0,0,0); rt1.transform.name = "rt1"; rt1.GetComponent<TextMesh>().text= "Bonus arrow"; } } /// <summary> /// 隐藏指引面板 /// </summary> public void showInstructions() { menuCanvas.enabled = false; instructionsCanvas.enabled = true; } /// <summary> /// 显示指引面板 /// </summary> public void hideInstructions() { menuCanvas.enabled = true; instructionsCanvas.enabled = false; } /// <summary> /// 显示最高得分 /// </summary> public void showHighscore() { menuCanvas.enabled = false; highscoreCanvas.enabled = true; actualHighscoreText.text = "Actual Hiscore: " + PlayerPrefs.GetInt ("Score") + " points"; newHighscoreText.text = "Your Score: " + score + " points"; if (score > PlayerPrefs.GetInt("Score")) newHighText.enabled = true; else newHighText.enabled = false; } /// <summary> /// 隐藏最高得分 /// </summary> public void hideHighScore() { menuCanvas.enabled = true; highscoreCanvas.enabled = false; if (score > PlayerPrefs.GetInt ("Score")) { PlayerPrefs.SetInt("Score",score); } resetGame(); } /// <summary> /// 检查最高分 /// </summary> public void checkHighScore() { gameOverCanvas.enabled = false; if (score > PlayerPrefs.GetInt ("Score")) { showHighscore(); } else { menuCanvas.enabled = true; resetGame(); } } /// <summary> /// 开始游戏 /// </summary> public void startGame() { menuCanvas.enabled = false; highscoreCanvas.enabled = false; instructionsCanvas.enabled = false; gameCanvas.enabled = true; gameState = GameStates.game; } /// <summary> /// 显示目录 /// </summary> public void showMenu() { menuCanvas.enabled = true; gameState = GameStates.menu; resetGame (); } }
using UnityEngine; using System.Collections; /// <summary> /// 控制弓箭 /// </summary> public class rotateArrow : MonoBehaviour { /// <summary> /// 是否已经 /// </summary> bool collisionOccurred; /// <summary> /// 箭的头部 /// </summary> public GameObject arrowHead; /// <summary> /// 伤害文本 /// </summary> public GameObject risingText; /// <summary> /// 弓 /// </summary> public GameObject bow; /// <summary> /// 击中目标的声音 /// </summary> public AudioClip targetHit; /// <summary> /// 透明度 /// </summary> float alpha; /// <summary> /// 剩余时间 /// </summary> float life_loss; /// <summary> /// 颜色 /// </summary> public Color color = Color.white; void Start () { float duration = 2f; life_loss = 1f / duration; alpha = 1f; } void Update () { //刚体不为空 if (transform.GetComponent<Rigidbody>() != null) { //速度不为0 if (GetComponent<Rigidbody>().velocity != Vector3.zero) { //获取速度 Vector3 vel = GetComponent<Rigidbody>().velocity; //计算旋转角度 float angleZ = Mathf.Atan2(vel.y,vel.x)*Mathf.Rad2Deg; float angleY = Mathf.Atan2(vel.z,vel.x)*Mathf.Rad2Deg; //沿着弓箭的轨道旋转箭 transform.eulerAngles = new Vector3(0,-angleY,angleZ); } } //如果发生了碰撞 if (collisionOccurred) { //改变透明度和颜色 alpha -= Time.deltaTime * life_loss; GetComponent<Renderer>().material.color = new Color(color.r,color.g,color.b,alpha); //如果透明度为0,删除物体 if (alpha <= 0f) { //创建新的箭 bow.GetComponent<bowAndArrow>().createArrow(true); Destroy(gameObject); } } } void OnCollisionEnter(Collision other) { //击中的位置 y轴 float y; //得分 int actScore = 0; //如果发生了碰撞 if (collisionOccurred) { //固定箭的位置 transform.position = new Vector3(other.transform.position.x,transform.position.y,transform.position.z); return; } ///如果碰到边界,销毁箭 if (other.transform.name == "Cube") { bow.GetComponent<bowAndArrow>().createArrow(false); Destroy(gameObject); } //如果碰到了目标 if (other.transform.name == "target") { //播放声音 GetComponent<AudioSource>().PlayOneShot(targetHit); //让速度归零 GetComponent<Rigidbody>().velocity = Vector3.zero; //让刚体不受重力影响 GetComponent<Rigidbody>().isKinematic = true; //让刚体不能发生旋转和位移 transform.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll; //设置标志位为true collisionOccurred = true; //隐藏箭头 arrowHead.SetActive(false); //修改y轴位置 y = other.contacts[0].point.y; y = y - other.transform.position.y; //射中白圈 if (y < 1.48557f && y > -1.48691f) actScore = 10; //射中黑圈 if (y < 1.36906f && y > -1.45483f) actScore = 20; //射中篮圈 if (y < 0.9470826f && y > -1.021649f) actScore = 30; //射中红圈 if (y < 0.6095f && y > -0.760f) actScore = 40; //射中金圈 if (y < 0.34f && y > -0.53f) actScore = 50; //创建得分文本 GameObject rt = (GameObject)Instantiate(risingText, new Vector3(0,0,0),Quaternion.identity); rt.transform.position = other.transform.position + new Vector3(-1,1,0); rt.transform.name = "rt"; rt.GetComponent<TextMesh>().text= "+"+actScore; bow.GetComponent<bowAndArrow>().setPoints(actScore); } } /// <summary> /// 设置弓 /// </summary> /// <param name="_bow"></param> public void setBow(GameObject _bow) { bow = _bow; } }
using UnityEngine; using System.Collections; /// <summary> /// 相机移动 /// </summary> public class camMovement : MonoBehaviour { /// <summary> /// 弓箭 /// </summary> public GameObject arrow; void Start () { arrow = null; } public void setArrow(GameObject _arrow) { arrow = _arrow; } /// <summary> /// 重置相机位置 /// </summary> public void resetCamera() { transform.position = new Vector3 (0, 0, -9.32f); } void Update () { //让摄像机跟随箭头移动 if (arrow != null) { Vector3 position = transform.position; float z = position.z; position = Vector3.Lerp (transform.position, arrow.transform.position, Time.deltaTime); position.z = z; transform.position = position; } } }
using UnityEngine; using System.Collections; /// <summary> /// 云层移动 /// </summary> public class cloudMove : MonoBehaviour { /// <summary> /// 移动速度 /// </summary> public float speed; void Update () { //获得当前位置 Vector3 position = transform.position; //设置新的x值 position.x += speed; //如果超出边界,重新移动到起始位置 if (position.x > 12f) position.x = -12f; //设置新的位置 transform.position = position; } }
using UnityEngine; using System.Collections; /// <summary> /// 向上飘的文字 /// </summary> [RequireComponent(typeof(TextMesh))] public class RisingText : MonoBehaviour { /// <summary> /// 移动的增量 /// </summary> Vector3 crds_delta; /// <summary> /// 透明度 /// </summary> float alpha; /// <summary> /// 每秒减少的透明度 /// </summary> float life_loss; /// <summary> /// 相机 /// </summary> Camera cam; /// <summary> /// 颜色 /// </summary> public Color color = Color.white; void Start() { //初始透明度 alpha = 1f; cam = GameObject.Find("Main Camera").GetComponent<Camera>(); //增量设置为向上 crds_delta = new Vector3(0f, 1f, 0f); life_loss = 0.5f; } void Update () { //向上移动 transform.Translate(crds_delta * Time.deltaTime, Space.World); //修改颜色 alpha -= Time.deltaTime * life_loss; GetComponent<Renderer>().material.color = new Color(color.r,color.g,color.b,alpha); //如果完全透明,删除物体 if (alpha <= 0f) Destroy(gameObject); //让物体朝向相机 transform.LookAt(cam.transform.position); transform.rotation = cam.transform.rotation; } }
视频:https://pan.baidu.com/s/1nva2xWt
项目:https://pan.baidu.com/s/1nvc4t9R