Unity3D 从入门到放弃(五)----射箭游戏

来源:互联网 发布:centos 安装openjdk 编辑:程序博客网 时间:2024/05/16 16:12

Unity3D 从入门到放弃(五)

—-射箭游戏

填坑啊填坑,每周都补上周作业,啥时候才能到头啊= =


作业需求

游戏规则:
设计一个射箭小游戏,点击鼠标射箭:
 靶对象为 5 环,按环计分;
 箭对象,射中后要插在靶上;
 游戏仅一轮,无限 trials;


实例化部分

本次作业有箭,靶两种实例,实现如下:

  1. 箭:
    箭分为三个部分,箭头,箭身,箭尾。
    箭头:通过一个圆锥和一个圆来实现。圆可以由高度为0的圆锥生成。箭头加上Mesh碰撞器并设置为触发器。(圆锥可以通过Editor文件夹中的CreateCone中创造的菜单实现)
    箭身:通过一个圆柱来实现。
    箭尾:通过两个双面四边形实现,由于unity3d默认渲染单面,因此要四个。(四边形可以通过Editor文件夹中的CreateRectangle中创造的菜单实现)
    为了添加重力,箭总体加入一个刚体。
    最后,将制作好的箭加入预设,作为初始物体。

  2. 靶:
    制作六个圆柱体,分别上不同颜色,并将内圈scale.Y的大小稍微调大一点以显示颜色,调整好角度,加上Mesh碰撞器即可。

  3. 文字框:
    通过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;        }    }}

0 0
原创粉丝点击