Unity3D 从入门到放弃(五)----射箭游戏
来源:互联网 发布:centos 安装openjdk 编辑:程序博客网 时间:2024/05/16 16:12
Unity3D 从入门到放弃(五)
—-射箭游戏
填坑啊填坑,每周都补上周作业,啥时候才能到头啊= =
作业需求
游戏规则:
设计一个射箭小游戏,点击鼠标射箭:
靶对象为 5 环,按环计分;
箭对象,射中后要插在靶上;
游戏仅一轮,无限 trials;
实例化部分
本次作业有箭,靶两种实例,实现如下:
箭:
箭分为三个部分,箭头,箭身,箭尾。
箭头:通过一个圆锥和一个圆来实现。圆可以由高度为0的圆锥生成。箭头加上Mesh碰撞器并设置为触发器。(圆锥可以通过Editor文件夹中的CreateCone中创造的菜单实现)
箭身:通过一个圆柱来实现。
箭尾:通过两个双面四边形实现,由于unity3d默认渲染单面,因此要四个。(四边形可以通过Editor文件夹中的CreateRectangle中创造的菜单实现)
为了添加重力,箭总体加入一个刚体。
最后,将制作好的箭加入预设,作为初始物体。靶:
制作六个圆柱体,分别上不同颜色,并将内圈scale.Y的大小稍微调大一点以显示颜色,调整好角度,加上Mesh碰撞器即可。文字框:
通过UI中的Text创建文字框,此处不再阐述。
效果如图:
箭:
靶:
打地基部分:
由于这次用的圆锥和四边形都不是unity3d自带的结构,因此需要自己创造。
首先,先创建一个Editor文件夹:(unity3d默认在Editor文件夹中的内容不能挂载,用于实现一些自动调用的脚本)
然后,在文件夹内添加CreateCone和CreateRectangle脚本:
脚本内容如下:
CreateCone:
/* * 描 述:用于创建圆锥的文件,我只是大自然的搬运工 * 作 者:hza * 创建时间:2017/04/06 13:20:14 * 版 本:v 1.0 */using UnityEngine;using UnityEditor;using System.Collections;public class CreateCone : ScriptableWizard{ /** * Num Vertices is the number of vertices each end will have. * Radius Top is the radius at the top. The center point will be located at (0/0/0). * Radius Bottom is the radius at the bottom. The center point will be located at (0/0/Length).(底圆的半径大小) * Length is the number of world units long the plane will be (+Z direction). * Opening Angle If this is >0, the top radius is set to 0, and the bottom radius is computed depending on the length, so that the given opening angle is created.(貌似是底圆是多少边形,即越大越接近圆形) * Outside defines whether the outside is visible (default). * Inside defines whether the inside is visible. Set both outside and inside to create a double-sided primitive. * Add Collider creates a matching mesh collider for the cone if checked. */ public int numVertices = 10; public float radiusTop = 0f; public float radiusBottom = 1f; public float length = 1f; public float openingAngle = 0f; // if >0, create a cone with this angle by setting radiusTop to 0, and adjust radiusBottom according to length; public bool outside = true; public bool inside = false; public bool addCollider = false; [MenuItem("GameObject/Create Other/Cone")] static void CreateWizard() { ScriptableWizard.DisplayWizard("Create Cone", typeof(CreateCone)); } void OnWizardCreate() { GameObject newCone = new GameObject("Cone"); if (openingAngle > 0 && openingAngle < 180) { radiusTop = 0; radiusBottom = length * Mathf.Tan(openingAngle * Mathf.Deg2Rad / 2); } string meshName = newCone.name + numVertices + "v" + radiusTop + "t" + radiusBottom + "b" + length + "l" + length + (outside ? "o" : "") + (inside ? "i" : ""); string meshPrefabPath = "Assets/Editor/" + meshName + ".asset"; Mesh mesh = (Mesh)AssetDatabase.LoadAssetAtPath(meshPrefabPath, typeof(Mesh)); if (mesh == null) { mesh = new Mesh(); mesh.name = meshName; // can't access Camera.current //newCone.transform.position = Camera.current.transform.position + Camera.current.transform.forward * 5.0f; int multiplier = (outside ? 1 : 0) + (inside ? 1 : 0); int offset = (outside && inside ? 2 * numVertices : 0); Vector3[] vertices = new Vector3[2 * multiplier * numVertices]; // 0..n-1: top, n..2n-1: bottom Vector3[] normals = new Vector3[2 * multiplier * numVertices]; Vector2[] uvs = new Vector2[2 * multiplier * numVertices]; int[] tris; float slope = Mathf.Atan((radiusBottom - radiusTop) / length); // (rad difference)/height float slopeSin = Mathf.Sin(slope); float slopeCos = Mathf.Cos(slope); int i; for (i = 0; i < numVertices; i++) { float angle = 2 * Mathf.PI * i / numVertices; float angleSin = Mathf.Sin(angle); float angleCos = Mathf.Cos(angle); float angleHalf = 2 * Mathf.PI * (i + 0.5f) / numVertices; // for degenerated normals at cone tips float angleHalfSin = Mathf.Sin(angleHalf); float angleHalfCos = Mathf.Cos(angleHalf); vertices[i] = new Vector3(radiusTop * angleCos, radiusTop * angleSin, 0); vertices[i + numVertices] = new Vector3(radiusBottom * angleCos, radiusBottom * angleSin, length); if (radiusTop == 0) normals[i] = new Vector3(angleHalfCos * slopeCos, angleHalfSin * slopeCos, -slopeSin); else normals[i] = new Vector3(angleCos * slopeCos, angleSin * slopeCos, -slopeSin); if (radiusBottom == 0) normals[i + numVertices] = new Vector3(angleHalfCos * slopeCos, angleHalfSin * slopeCos, -slopeSin); else normals[i + numVertices] = new Vector3(angleCos * slopeCos, angleSin * slopeCos, -slopeSin); uvs[i] = new Vector2(1.0f * i / numVertices, 1); uvs[i + numVertices] = new Vector2(1.0f * i / numVertices, 0); if (outside && inside) { // vertices and uvs are identical on inside and outside, so just copy vertices[i + 2 * numVertices] = vertices[i]; vertices[i + 3 * numVertices] = vertices[i + numVertices]; uvs[i + 2 * numVertices] = uvs[i]; uvs[i + 3 * numVertices] = uvs[i + numVertices]; } if (inside) { // invert normals normals[i + offset] = -normals[i]; normals[i + numVertices + offset] = -normals[i + numVertices]; } } mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uvs; // create triangles // here we need to take care of point order, depending on inside and outside int cnt = 0; if (radiusTop == 0) { // top cone tris = new int[numVertices * 3 * multiplier]; if (outside) for (i = 0; i < numVertices; i++) { tris[cnt++] = i + numVertices; tris[cnt++] = i; if (i == numVertices - 1) tris[cnt++] = numVertices; else tris[cnt++] = i + 1 + numVertices; } if (inside) for (i = offset; i < numVertices + offset; i++) { tris[cnt++] = i; tris[cnt++] = i + numVertices; if (i == numVertices - 1 + offset) tris[cnt++] = numVertices + offset; else tris[cnt++] = i + 1 + numVertices; } } else if (radiusBottom == 0) { // bottom cone tris = new int[numVertices * 3 * multiplier]; if (outside) for (i = 0; i < numVertices; i++) { tris[cnt++] = i; if (i == numVertices - 1) tris[cnt++] = 0; else tris[cnt++] = i + 1; tris[cnt++] = i + numVertices; } if (inside) for (i = offset; i < numVertices + offset; i++) { if (i == numVertices - 1 + offset) tris[cnt++] = offset; else tris[cnt++] = i + 1; tris[cnt++] = i; tris[cnt++] = i + numVertices; } } else { // truncated cone tris = new int[numVertices * 6 * multiplier]; if (outside) for (i = 0; i < numVertices; i++) { int ip1 = i + 1; if (ip1 == numVertices) ip1 = 0; tris[cnt++] = i; tris[cnt++] = ip1; tris[cnt++] = i + numVertices; tris[cnt++] = ip1 + numVertices; tris[cnt++] = i + numVertices; tris[cnt++] = ip1; } if (inside) for (i = offset; i < numVertices + offset; i++) { int ip1 = i + 1; if (ip1 == numVertices + offset) ip1 = offset; tris[cnt++] = ip1; tris[cnt++] = i; tris[cnt++] = i + numVertices; tris[cnt++] = i + numVertices; tris[cnt++] = ip1 + numVertices; tris[cnt++] = ip1; } } mesh.triangles = tris; AssetDatabase.CreateAsset(mesh, meshPrefabPath); AssetDatabase.SaveAssets(); } MeshFilter mf = newCone.AddComponent<MeshFilter>(); mf.mesh = mesh; newCone.AddComponent<MeshRenderer>(); if (addCollider) { MeshCollider mc = newCone.AddComponent<MeshCollider>(); mc.sharedMesh = mf.sharedMesh; } Selection.activeObject = newCone; }}
CreateRectangle:
/* * 描 述:用于创建四边形的文件,我只是大自然的搬运工 * 作 者:hza * 创建时间:2017/04/06 13:50:10 * 版 本:v 1.0 */using UnityEngine;using UnityEditor;using System.Collections;public class CreateRectangle : ScriptableWizard{ /* 属性含义: * width: 四边形宽度(x轴) * length: 四边形高度(z轴) * angle: 两边的夹角,默认为90°[0, 180] * addCollider: 是否需要添加碰撞器,默认为false */ public float width = 1; public float length = 1; public float angle = 90; public bool addCollider = false; [MenuItem("GameObject/Create Other/Rectangle")] static void CreateWizard() { ScriptableWizard.DisplayWizard("Create Rectangle", typeof(CreateRectangle)); } void OnWizardCreate() { GameObject newRectangle = new GameObject("Rectangle"); // 保存mash的名字和路径 string meshName = newRectangle.name + "w" + width + "l" + length + "a" + angle; string meshPrefabPath = "Assets/Editor/" + meshName + ".asset"; // 对角度进行处理 while (angle > 180) angle -= 180; while (angle < 0) angle += 180; angle *= Mathf.PI / 180; /* 1. 顶点,三角形,法线,uv坐标, 绝对必要的部分只有顶点和三角形。 * 如果模型中不需要场景中的光照,那么就不需要法线。 * 如果模型不需要贴材质,那么就不需要UV */ Vector3[] vertices = new Vector3[4]; Vector3[] normals = new Vector3[4]; Vector2[] uv = new Vector2[4]; vertices[0] = new Vector3(0, 0, 0); uv[0] = new Vector2(0, 0); normals[0] = Vector3.up; vertices[1] = new Vector3(0, 0, length); uv[1] = new Vector2(0, 1); normals[1] = Vector3.up; vertices[2] = new Vector3(width * Mathf.Sin(angle), 0, length + width * Mathf.Cos(angle)); uv[2] = new Vector2(1, 1); normals[2] = Vector3.up; vertices[3] = new Vector3(width * Mathf.Sin(angle), 0, width * Mathf.Cos(angle)); uv[3] = new Vector2(1, 0); normals[3] = Vector3.up; /* 2. 三角形,顶点索引: * 三角形是由3个整数确定的,各个整数就是角的顶点的index。 * 各个三角形的顶点的顺序通常由下往上数, 可以是顺时针也可以是逆时针,这通常取决于我们从哪个方向看三角形。 * 通常,当mesh渲染时,"逆时针" 的面会被挡掉。 我们希望保证顺时针的面与法线的主向一致 */ int[] indices = new int[6]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; Mesh mesh = new Mesh(); mesh.name = meshName; mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.triangles = indices; mesh.RecalculateBounds(); AssetDatabase.CreateAsset(mesh, meshPrefabPath); AssetDatabase.SaveAssets(); // 添加MeshFilter MeshFilter filter = newRectangle.gameObject.AddComponent<MeshFilter>(); if (filter != null) { filter.sharedMesh = mesh; } // 添加MeshRendered MeshRenderer meshRender = newRectangle.gameObject.AddComponent<MeshRenderer>(); Shader shader = Shader.Find("Standard"); meshRender.sharedMaterial = new Material(shader); // 如果愿意添加碰撞器,则添加碰撞器 if (addCollider) { MeshCollider mc = newRectangle.AddComponent<MeshCollider>(); mc.sharedMesh = filter.sharedMesh; } Selection.activeObject = newRectangle; }}
脚本放进去后,可以在Hierarchy里的create找到createother这个选项了,然后就可以自己创造圆锥和四边形啦。
逻辑部分
老规矩,先放UML图:
(和上次做业大体逻辑一样,仅仅是多了几个挂载脚本)
代码如下:
BaseAction:
/* * 描 述:基类动作文件 * 作 者:hza * 创建时间:2017/04/07 17:39:08 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;namespace Tem.Action{ public enum SSActionEventType : int { STARTED, COMPLETED } public interface ISSActionCallback { void SSEventAction(SSAction source, SSActionEventType events = SSActionEventType.COMPLETED, int intParam = 0, string strParam = null, Object objParam = null); } public class SSAction : ScriptableObject // 动作的基类 { public bool enable = true; public bool destory = false; public GameObject gameObject { get; set; } public Transform transform { get; set; } public ISSActionCallback callback { get; set; } public virtual void Start() { throw new System.NotImplementedException("Action Start Error!"); } public virtual void FixedUpdate() { throw new System.NotImplementedException("Physics Action Start Error!"); } public virtual void Update() { throw new System.NotImplementedException("Action Update Error!"); } } public class CCMoveToAction : SSAction { public Vector3 target; public float speed; public static CCMoveToAction GetSSAction(Vector3 _target, float _speed) { CCMoveToAction currentAction = ScriptableObject.CreateInstance<CCMoveToAction>(); currentAction.target = _target; currentAction.speed = _speed; return currentAction; } public override void Start() { } public override void Update() { this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed * Time.deltaTime); if (this.transform.position == target) { this.destory = true; this.callback.SSEventAction(this); } } } public class CCBezierMoveAction : SSAction // 仅用于三次贝塞尔曲线 { public List<Vector3> vectors; public Vector3 target; public float speed; private Vector3 begin; private float t; private bool firstTime; /*private Vector3 vector2begin; private Vector3 vector2mid; private Vector3 vector2end; private Vector3 vector3begin; private Vector3 vector3end; private float timeBegin; private float timeDiff;*/ public static CCBezierMoveAction GetCCBezierMoveAction(List<Vector3> _vectors, float _speed) // vector里面最后一个值是目标位置 { CCBezierMoveAction action = ScriptableObject.CreateInstance<CCBezierMoveAction>(); action.vectors = _vectors; action.target = _vectors[_vectors.Count - 1]; action.vectors.RemoveAt(action.vectors.Count - 1); action.speed = _speed; return action; } public override void Start() // 公式写法 { //timeDiff = 0; firstTime = true; t = 0; } public override void Update() { if (firstTime) { speed = speed / Vector3.Distance(this.transform.position, target) / 1.5f; // 速度除以相对距离并除以2作为速度比 begin = this.transform.position; firstTime = false; } t += Time.deltaTime * speed; if (t > 1) t = 1; float _t = 1 - t; this.transform.position = begin * Mathf.Pow(_t, 3) + 3 * vectors[0] * Mathf.Pow(_t, 2) * t + 3 * vectors[1] * _t * Mathf.Pow(t, 2) + target * Mathf.Pow(t, 3); if (this.transform.position == target) { this.destory = true; this.callback.SSEventAction(this); } } /*public override void Update() // 正常写法 { timeDiff += Time.deltaTime; vector2begin = Vector3.Lerp(this.transform.position, vectors[0], speed * timeDiff); vector2mid = Vector3.Lerp(vectors[0], vectors[1], speed * timeDiff); vector2end = Vector3.Lerp(vectors[1], target, speed * timeDiff); // 第一次计算差值 vector3begin = Vector3.Lerp(vector2begin, vector2mid, speed * timeDiff); vector3end = Vector3.Lerp(vector2mid, vector2end, speed * timeDiff); // 第二次计算差值 this.transform.position = Vector3.Lerp(vector3begin, vector3end, speed * timeDiff); // 最后一次计算差值 if (this.transform.position == target) { this.destory = true; this.callback.SSEventAction(this); } }*/ } public class CCSequenceAction : SSAction, ISSActionCallback { public List<SSAction> sequence; public int repeat = -1; public int start = 0; public static CCSequenceAction GetSSAction(List<SSAction> _sequence, int _start = 0, int _repead = 1) { CCSequenceAction actions = ScriptableObject.CreateInstance<CCSequenceAction>(); actions.sequence = _sequence; actions.start = _start; actions.repeat = _repead; return actions; } public override void Start() { foreach (SSAction ac in sequence) { ac.gameObject = this.gameObject; ac.transform = this.transform; ac.callback = this; ac.Start(); } } public override void Update() { if (sequence.Count == 0) return; if (start < sequence.Count) sequence[start].Update(); } public void SSEventAction(SSAction source, SSActionEventType events = SSActionEventType.COMPLETED, int intParam = 0, string strParam = null, Object objParam = null) //通过对callback函数的调用执行下个动作 { source.destory = false; // 当前动作不能销毁(有可能执行下一次) this.start++; if (this.start >= this.sequence.Count) { this.start = 0; if (this.repeat > 0) repeat--; if (this.repeat == 0) { this.destory = true; this.callback.SSEventAction(this); } } } private void OnDestroy() { this.destory = true; } } public class SSActionManager : MonoBehaviour { private Dictionary<int, SSAction> dictionary = new Dictionary<int, SSAction>(); private List<SSAction> watingAddAction = new List<SSAction>(); private List<int> watingDelete = new List<int>(); protected void Start() { } protected void Update() { foreach (SSAction ac in watingAddAction) dictionary[ac.GetInstanceID()] = ac; watingAddAction.Clear(); // 将待加入动作加入dictionary执行 foreach (KeyValuePair<int, SSAction> dic in dictionary) { SSAction ac = dic.Value; if (ac.destory) watingDelete.Add(ac.GetInstanceID()); else if (ac.enable) ac.Update(); } // 如果要删除,加入要删除的list,否则更新 foreach (int id in watingDelete) { SSAction ac = dictionary[id]; dictionary.Remove(id); DestroyObject(ac); } watingDelete.Clear(); // 将deletelist中的动作删除 } public void runAction(GameObject gameObject, SSAction action, ISSActionCallback callback) { action.gameObject = gameObject; action.transform = gameObject.transform; action.callback = callback; watingAddAction.Add(action); action.Start(); } } public class PYActionManager : MonoBehaviour { private Dictionary<int, SSAction> dictionary = new Dictionary<int, SSAction>(); private List<SSAction> watingAddAction = new List<SSAction>(); private List<int> watingDelete = new List<int>(); protected void Start() { } protected void FixedUpdate() { foreach (SSAction ac in watingAddAction) dictionary[ac.GetInstanceID()] = ac; watingAddAction.Clear(); // 将待加入动作加入dictionary执行 foreach (KeyValuePair<int, SSAction> dic in dictionary) { SSAction ac = dic.Value; if (ac.destory) watingDelete.Add(ac.GetInstanceID()); else if (ac.enable) ac.FixedUpdate(); } // 如果要删除,加入要删除的list,否则更新 foreach (int id in watingDelete) { SSAction ac = dictionary[id]; dictionary.Remove(id); DestroyObject(ac); } watingDelete.Clear(); // 将deletelist中的动作删除 } public void runAction(GameObject gameObject, SSAction action, ISSActionCallback callback) { action.gameObject = gameObject; action.transform = gameObject.transform; action.callback = callback; watingAddAction.Add(action); action.Start(); } }}
BaseCode:
/* * 描 述:设置游戏基本信息 * 作 者:hza * 创建时间:2017/04/07 20:29:47 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;public class BaseCode : MonoBehaviour{ public string GameName; public string GameRule; void Start() { GameName = "Shoot"; GameRule = "左键点击射箭,射中靶子加分,靶心从内到外分别为60-10分,点击clear清除所有的箭"; }}
ChangeCamera:
/* * 描 述:射中后,摄像头拉近,持续两秒 * 作 者:hza * 创建时间:2017/04/07 14:46:35 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;public class ChangeCamera : MonoBehaviour { public GameObject mainCamera; public GameObject closeCamera; // 引用两个摄像机 bool active; float beginTime; private void Start() { active = false; } // Update is called once per frame void Update () { if (!active) return; beginTime -= Time.deltaTime; if (beginTime < 0) { resetCount(); } } // 显示近身摄像机,持续2秒 public void ShowCloseCamera() { mainCamera.SetActive(false); closeCamera.SetActive(true); // 显示close摄像机 runCount(); } void runCount() { active = true; beginTime = 2f; // 激活计数按钮 } void resetCount() { active = false; mainCamera.SetActive(true); closeCamera.SetActive(false); }}
MouseRotate:
/* * 描 述:控制摄像机随鼠标移动的脚本,挂载在摄像机上即可 * 作 者:hza * 创建时间:2017/04/07 17:01:57 * 版 本:v 1.0 */using UnityEngine;using System.Collections;using System.Collections.Generic;//[AddComponentMenu("Camera-Control/Mouse Look")]public class MouseRotate : MonoBehaviour { public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 } public RotationAxes axes = RotationAxes.MouseXAndY; // 鼠标移动方式 public float sensitivityX = 15F; public float sensitivityY = 15F; // 灵敏度 public float minimumX = -360F; public float maximumX = 360F; // X最大偏移 public float minimumY = -60F; public float maximumY = 60F; // Y最大偏移 public bool isVisible = true; // 鼠标是否可见 float rotationY = 0F; float rotationX = 0F; void Start() { // Make the rigid body not change rotation if (GetComponent<Rigidbody>()) GetComponent<Rigidbody>().freezeRotation = true; } void Update() { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = isVisible; // 鼠标保持在屏幕中间 if (axes == RotationAxes.MouseXAndY) { rotationX += Input.GetAxis("Mouse X") * sensitivityX; rotationX = Mathf.Clamp(rotationX, minimumX, maximumX); rotationY += Input.GetAxis("Mouse Y") * sensitivityY; rotationY = Mathf.Clamp(rotationY, minimumY, maximumY); this.transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0); } else if (axes == RotationAxes.MouseX) { rotationX += Input.GetAxis("Mouse X") * sensitivityX; rotationX = Mathf.Clamp(rotationX, minimumX, maximumX); this.transform.localEulerAngles = new Vector3(0, rotationX, 0); } else { rotationY += Input.GetAxis("Mouse Y") * sensitivityY; rotationY = Mathf.Clamp(rotationY, minimumY, maximumY); this.transform.localEulerAngles = new Vector3(-rotationY, 0, 0); } }}
RowActionManager:
/* * 描 述:用于控制箭发射的动作类 * 作 者:hza * 创建时间:2017/04/07 18:23:30 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;using Tem.Action;using UnityEngine.UI;public class RowAction : SSAction{ private Vector3 beginV; public static RowAction GetRowAction(Vector3 beginV) { RowAction currentAction = ScriptableObject.CreateInstance<RowAction>(); currentAction.beginV = beginV; return currentAction; } public override void Start() { this.gameObject.GetComponent<Rigidbody>().velocity = beginV; // 设置初始速度 } public override void FixedUpdate() { // 如果掉下去,返回 if (this.transform.position.y < -2) { this.destory = true; this.callback.SSEventAction(this); // 进行回调操作 } }}public class RowActionManager : PYActionManager, ISSActionCallback { public GameObject cam; public GameObject target; public Text scoretext; private SceneController scene; // 控制该动作的场景 // Use this for initialization new void Start () { scene = Singleton<SceneController>.Instance; } // Update is called once per frame new void FixedUpdate () { base.FixedUpdate(); if (cam.activeSelf && Input.GetMouseButtonDown(0)) // 左键点击 { RowFactory fac = Singleton<RowFactory>.Instance; GameObject row = fac.setObjectOnPos(cam.transform.position, cam.transform.localRotation); if (row.GetComponent<Rigidbody>() == null) row.AddComponent<Rigidbody>(); row.transform.FindChild("RowHead").gameObject.SetActive(true); Debug.Log(row.transform.FindChild("RowHead").gameObject.activeSelf); Transform head = row.transform.FindChild("RowHead").FindChild("OutCone"); if (head.gameObject.GetComponent<RowHeadTrigger>() == null) { head.gameObject.AddComponent<RowHeadTrigger>(); head.gameObject.GetComponent<RowHeadTrigger>().Target = target; head.gameObject.GetComponent<RowHeadTrigger>().scoretext = scoretext; } // 得到物体,如果未添加脚本就设置脚本,并设置active RowAction action = RowAction.GetRowAction(cam.transform.forward * 30); // 得到动作 this.runAction(row, action, this); } } // 回调函数 public void SSEventAction(SSAction source, SSActionEventType events = SSActionEventType.COMPLETED, int intParam = 0, string strParam = null, Object objParam = null) { RowFactory fac = Singleton<RowFactory>.Instance; fac.freeObject(source.gameObject); }}
RowFactory:
/* * 描 述:用于加载Row的工厂 * 作 者:hza * 创建时间:2017/04/07 17:31:37 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;public class RowFactory : MonoBehaviour{ private static List<GameObject> used = new List<GameObject>(); // 正在使用的对象链表 private static List<GameObject> free = new List<GameObject>(); // 正在空闲的对象链表 // 此函数表示将Target物体放到一个位置 public GameObject setObjectOnPos(Vector3 targetposition, Quaternion faceposition) { if (free.Count == 0) { GameObject aGameObject = Instantiate(Resources.Load("prefabs/Row") , targetposition, faceposition) as GameObject; // 新建实例,将位置设置成为targetposition,将面向方向设置成faceposition used.Add(aGameObject); } else { used.Add(free[0]); free.RemoveAt(0); used[used.Count - 1].SetActive(true); used[used.Count - 1].transform.position = targetposition; used[used.Count - 1].transform.localRotation = faceposition; } return used[used.Count - 1]; } public void freeObject(GameObject oj) { oj.SetActive(false); used.Remove(oj); free.Add(oj); } public void freeAllObject() { if (used.Count == 0) return; for (int i = 0; i < used.Count; i++) { used[i].SetActive(false); free.Add(used[i]); } used.Clear(); Debug.Log(used.Count); Debug.Log(free.Count); // 清除used里面所有物体 }}
RowHeadTrigger:
/* * 描 述:放在rowhead物体上,写触发函数 * 作 者:hza * 创建时间:2017/04/07 13:57:17 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class RowHeadTrigger : MonoBehaviour { public GameObject Target; public Text scoretext; // Use this for initialization void Start () { } // Update is called once per frame void OnTriggerEnter(Collider e) { if (e.gameObject.tag == "Round") { float realDistance = Vector2.Distance(this.transform.position, Target.transform.position); float imagDistance = (1 + (e.gameObject.name[5] - '1') * 2) * 0.5f; int score; if (realDistance + 0.1 < imagDistance) score = (6 - (int)(realDistance * 10)) * 10; else score = (e.gameObject.name[5] - '0') * 10; ScoreRecorder scorerecorder = ScoreRecorder.getInstance(scoretext); scorerecorder.addScore(score); // 添加分数 Destroy(this.transform.parent.parent.GetComponent<Rigidbody>()); ChangeCamera ch = Singleton<ChangeCamera>.Instance; ch.ShowCloseCamera(); // 切换相机 } }}
SceneController:
/* * 描 述:场景和UI控制 * 作 者:hza * 创建时间:2017/04/07 17:33:39 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;public class SceneController : MonoBehaviour{ void Start() { LoadResources(); } public void LoadResources() // 加载初始物体 { GameObject target = Instantiate(Resources.Load("prefabs/Target"), new Vector3(0, 0, -5), Quaternion.identity) as GameObject; Instantiate(Resources.Load("prefabs/Wall"), Vector3.zero, Quaternion.Euler(new Vector3(-90, 0, 0))); Instantiate(Resources.Load("prefabs/Floor"), new Vector3(0, -2, -12), Quaternion.identity); RowActionManager actionmanager = Singleton<RowActionManager>.Instance; actionmanager.target = target; // 创建实例 } private void OnGUI() { if (Input.GetKey(KeyCode.F)) { BaseCode bc = Singleton<BaseCode>.Instance; GUI.TextArea(new Rect(Screen.width / 4, Screen.height - 50, Screen.width / 2, 40), bc.GameRule); } // resetgame if (Input.GetKeyDown(KeyCode.R)) { RowFactory fac = Singleton<RowFactory>.Instance; fac.freeAllObject(); } }}
ScoreRecorder:
/* * 描 述:用于计算分数 * 作 者:hza * 创建时间:2017/04/07 20:03:57 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class ScoreRecorder{ public Text scoreText; // 计分板 private int score; // 纪录分数 private static ScoreRecorder _instance; public static ScoreRecorder getInstance(Text _scoreText) { if (_instance == null) { _instance = new ScoreRecorder(); _instance.scoreText = _scoreText; _instance.resetScore(); } return _instance; } // 单实例 public void resetScore() { score = 0; } // 飞碟点击中加分 public void addScore(int addscore) { score += addscore; scoreText.text = "Score:" + score; } public void setDisActive() { scoreText.text = ""; } public void setActive() { scoreText.text = "Score:" + score; }}
Singleton:
/* * 描 述:单实例模板 * 作 者:hza * 创建时间:2017/04/07 14:58:51 * 版 本:v 1.0 */using System.Collections;using System.Collections.Generic;using UnityEngine;public class Singleton<T> : MonoBehaviour where T : MonoBehaviour { // 私有static变量 protected 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 it not!"); } } return instance; } }}
- Unity3D 从入门到放弃(五)----射箭游戏
- JavaScript从入门到放弃(五)
- Unity3D 从入门到放弃(四)----打飞碟
- Unity3D 从入门到放弃(六)-----巡逻兵
- Unity3D从入门到放弃(七) ----DoTween的实现
- 微信小程序从入门到放弃(五)
- Python从入门到放弃(五):类细讲
- OpenCV从入门到放弃(五):像素!
- Python从入门到放弃(五):类细讲
- Unity3D学习(8)之射箭游戏
- Unity3D学习(四)射箭游戏
- NDK开发 从入门到放弃(五:JNI抛异常)
- UnityShader从入门到放弃(五)漫反射—逐片元光照
- Docker 从入门到放弃(一)
- 策略模式(从放弃到入门)
- 观察者模式(从放弃到入门)
- JSP--(二)从入门到放弃
- Kotlin从入门到“放弃”(一)
- PyJWT翻译
- Centos 6.9 iptables 开启端口 5050,5151 等
- Web.xml配置详解之context-param
- Shell .sh,for, if, 变量的使用
- 深入理解HTTP协议
- Unity3D 从入门到放弃(五)----射箭游戏
- mysql和postgres数据库性能比较
- 打破外网插件,ngrok的使用
- python找出完数
- BZOJ P1821[JSOI2010]Group部落划分
- Docker 学习笔记
- Android Studio 快捷键
- 菜鸟爬虫-爬妹子图
- Intellij idea 创建一个简单的javaweb项目