Unity实现3D射箭小游戏

Unity 小游戏:3D射箭,供大家参考,具体内容如下

前两周因为实训太忙,再加上自己对老师所讲的设计模式并不是很理解,所以就没有写博客。这次博客是记录3D射箭游戏的实现过程。

1. 准备资源

我是在网上找的弓与箭的资源,至于靶子,创建五个不同大小的同心圆柱体,如图所示:

需要注意的是,五个圆柱体并不在同一个平面上,这样才能够看清每一环的颜色,并且在检测碰撞时不会出现各种问题。

另外,如果靶子放得离相机太近,就没有射箭的感觉了;离相机太远,好像又看不清靶子了,然后我试着把靶子MaterialShader改为 Sprites/Default ,这样靶子离相机远一点也能看得很清晰。

2. 布置场景

把弓箭作为Main Camera的子物体,这样我们可以在用鼠标控制镜头移动时,使弓箭一直指向屏幕中心,以达到第一人称控制器的效果。

在此项目中,没有选择使用GUI来做UI界面,而是创建了一个Canvas,在这里面添加了一个Image用来显示弓箭的准心,以及四个Text来显示得分、风向、风力、提示等。

3. 编辑脚本

游戏采用MVC架构,大部分功能是自己实现的,也有一小些函数是借鉴大神的。整体上感觉有很多缺陷,但是又不知道怎么修改才好,我也很无奈啊!°(°ˊДˋ°) °

下面是我的UML图:

以下是完整代码:

SSDirector.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SSDirector : System.Object {

    private static SSDirector _instance;

    public ISceneCotroller currentScenceCotroller {
        get;
        set;
    }

    public bool running {
        get;
        set;
    }

    public static SSDirector getInstance() {
        if (_instance == null) {
            _instance = new SSDirector ();
        }
        return _instance;
    }
}

ISceneCotroller.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface ISceneCotroller {
    void LoadResources ();
}

IUserAction.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface IUserAction {
    string getMyScore ();
    float getWind ();
    void Openbow ();
    void Draw ();
    void Shoot ();
}

ActionManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine; 

public class ActionManager : MonoBehaviour {

    private float Force = 0f;
    private int maxPower = 2500;
    private float power;
    public Transform arrowSpawn;
    public Transform myArrow;
    public Transform bow;

    //播放拉弓动画
    public void Openbow () {
        bow.GetComponent<Animation>().Play("Draw");
        bow.GetComponent<Animation>()["Draw"].speed = 1;
        bow.GetComponent<Animation>()["Draw"].wrapMode = WrapMode.Once;

        arrowSpawn.GetComponent<MeshRenderer>().enabled = true;

        //重置 power 为 0
        power = 0;
    }

    //拉弓,从power为0到power为3000
    public void Draw () {
        if(power < maxPower) {
            power += maxPower * Time.deltaTime;
        }
    }

    //射箭
    public void Shoot () {
        float percent = bow.GetComponent<Animation>()["Draw"].time / bow.GetComponent<Animation>()["Draw"].length;
        float shootTime = 1 * percent;

        bow.GetComponent<Animation>().Play("Shoot");
        bow.GetComponent<Animation>()["Shoot"].speed = 1;
        bow.GetComponent<Animation>()["Shoot"].time = shootTime;
        bow.GetComponent<Animation>()["Shoot"].wrapMode = WrapMode.Once;

        arrowSpawn.GetComponent<MeshRenderer>().enabled = false;
        Transform arrow= Instantiate (myArrow, arrowSpawn.transform.position, transform.rotation);
        arrow.transform.GetComponent<Rigidbody>().AddForce(transform.forward * power);

        wind (arrow);
        Force = Random.Range (-100, 100);
    }

    //产生风
    private void wind(Transform arrow) {
        arrow.transform.GetComponent<Rigidbody> ().AddForce (new Vector3 (Force, 0, 0), ForceMode.Force);
    }

    //返回风
    public float getWindForce() {
        return Force;
    }
}

ScoreRecorder.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine; 

public class ScoreRecorder : MonoBehaviour {

    private string Score = "0";

    //判断得分
    public void countScore(string type) {
        Score = type;
    }

    //返回分数
    public string getScore () {
        return Score;
    }
}

FirstScene.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FirstScene : MonoBehaviour, ISceneCotroller, IUserAction {

    private ActionManager actionManager;
    private ScoreRecorder scoreRecorder;

    void Awake () {
        SSDirector director = SSDirector.getInstance ();
        director.currentScenceCotroller = this;
        director.currentScenceCotroller.LoadResources ();
        actionManager = (ActionManager)FindObjectOfType (typeof(ActionManager));
        scoreRecorder = (ScoreRecorder)FindObjectOfType (typeof(ScoreRecorder));
    }

    //加载预制物体靶子
    public void LoadResources () {
        Debug.Log ("loading...\n");
        GameObject target = Instantiate<GameObject> (
                                Resources.Load<GameObject> ("Prefabs/target"));
        target.name = "target";
    }

    //获得分数
    public string getMyScore () {
        return scoreRecorder.getScore ();
    }

    //获得风向和风力
    public float getWind () {
        return actionManager.getWindForce ();
    }

    //拉弓
    public void Openbow () {
        actionManager.Openbow ();
    }

    //蓄力
    public void Draw () {
        actionManager.Draw ();
    }

    //射箭
    public void Shoot () {
        actionManager.Shoot ();
    }
}

UserGUI.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UserGUI : MonoBehaviour {

    private IUserAction userAction;
    private FirstScene scene;
    private Quaternion m_CharacterTargetRot;

    public Text Score;
    public Text WindDirection;
    public Text WindForce;

    // Use this for initialization
    void Start () {
        userAction = SSDirector.getInstance ().currentScenceCotroller as IUserAction;
    }

    void Awake () {
        m_CharacterTargetRot = transform.localRotation;
    }

    void Update () {
        //镜头跟随鼠标
        float xRot = Input.GetAxis ("Mouse X") * 3f;
        float yRot = Input.GetAxis ("Mouse Y") * -3f;
        m_CharacterTargetRot *= Quaternion.Euler (yRot, xRot, 0f);
        transform.localRotation = Quaternion.Slerp (transform.localRotation, m_CharacterTargetRot,
            5f * Time.deltaTime);

        //按空格键使弓箭瞄准靶心
        if (Input.GetKeyDown (KeyCode.Space)) {
            m_CharacterTargetRot = Quaternion.Euler (0f, 0f, 0f);
            transform.localRotation = Quaternion.Slerp (transform.localRotation, m_CharacterTargetRot,
                5f * Time.deltaTime);
        }

        //鼠标左键按下,开始拉弓
        if (Input.GetMouseButtonDown (0)) {
            userAction.Openbow ();
        }

        //鼠标左键按住不放,蓄力
        if (Input.GetMouseButton (0)) {
            userAction.Draw ();
        }

        //鼠标左键抬起。射箭
        if (Input.GetMouseButtonUp (0)) {
            userAction.Shoot ();
        }

        Score.text = "Score : " + userAction.getMyScore ();     //显示上一轮分数
        float force = userAction.getWind ();
        if (force < 0) {
            WindDirection.text = "Wind Direction : <---";       //显示风向
        } else if (force > 0) {
            WindDirection.text = "Wind Direction : --->";
        } else {
            WindDirection.text = "Wind Direction : No";
        }
        WindForce.text = "Wind Force : " + Mathf.Abs (userAction.getWind ()); //显示风力
    }
}

Arrow.cs

using UnityEngine;
using System.Collections;

public class Arrow : MonoBehaviour {

    private RaycastHit hit;

    void  Update (){
        //检测在移动的箭
        if(GetComponent<Rigidbody>().velocity.magnitude > 0.5f) {
            CheckForHit();
        } else {
            enabled = false;
        }
        if (transform.position.y < -5) {
            Destroy (this.gameObject);      //将掉出地面以下的箭销毁
        }
    }

    //检测是否碰撞
    void CheckForHit (){
        float myVelocity = GetComponent<Rigidbody>().velocity.magnitude;
        float raycastLength = myVelocity * 0.03f;

        if(Physics.Raycast(transform.position, transform.forward, out hit, raycastLength)) {
            GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;     //使箭停留在靶子上
            transform.position = hit.point;
            transform.parent = hit.transform;
            enabled = false;
        } else {
            Quaternion newRot = transform.rotation;
            newRot.SetLookRotation(GetComponent<Rigidbody>().velocity);
            transform.rotation = newRot;    //箭没中靶,则继续做抛物线运动
        }
    }
}

Target.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Target : MonoBehaviour {

    private ScoreRecorder scoreRecorder;

    public string score;    //对应靶环的分数

    public void Start() {
        scoreRecorder = (ScoreRecorder)FindObjectOfType (typeof(ScoreRecorder));
    }

    void OnTriggerEnter(Collider other) {
        if (other.gameObject.tag == "Arrow") {
            scoreRecorder.countScore (score);       //记录分数
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Unity 如何通过反射给gameObject添加组件

    C#版本 public static Component AddComponent(GameObject go, string assembly, string classname) { var asmb = System.Reflection.Assembly.Load(assembly); var t = asmb.GetType(assembly + "." + classname); if(null != t) return go.AddComponent(t); else r

  • Unity实现老虎机滚动抽奖效果的示例代码

    直接看下效果图吧: 制作思路: 设计四张图片,五个点,每个图片同时向下一个点移动,到最后一个就回到0号点,以此循环. 场景搭建: 创建Image命名为Bg作为电视框背景: 创建Image命名Mask并添加Mask组件作为电视框内容显示遮罩框: 创建四个Image作为滚动图片: 创建开始抽奖按钮: PS:实际项目中可以根据需求来动态修改图片显示,以达到的控制每次抽奖奖品内容. 源码分享: using System.Collections; using UnityEngine; using Unit

  • Unity之跑马灯抽奖效果单抽与连抽(附demo)

    本文主要介绍了Unity之跑马灯抽奖效果单抽与连抽,分享给大家,具体如下: 效果图 单次抽奖效果 跳过动画抽奖效果 三连抽抽奖效果 设计思路 点击按钮 ,根据需求(概率)计算本次抽奖获得物品模拟转动 (先加速后减速), 一段时间后停止连抽的情况下等所有奖品动画都表演完成才结束跳过动画设计,有跳过时抽奖速度直接到最大,并进入可中奖 场景搭建 一个按钮,一个组奖品放到一个父物体上. 奖品元素,有两种状态,一种旋转状态,一种中奖状态. 代码 using System; using System.Col

  • Unity实现模型点击事件的方法

    模型点击事件监听 触发模型点击事件的必要条件 需要触发模型点击事件的模型身上必须要挂载Collider 组件 方法一 通过 OnMouseDown 函数监听(只能在PC端有效) 1.在Hierarchy 面板中右键,点击 3D Object->Cube 按钮,创建一个 Cube 模型 2.新建一个脚本,命名为"Test.cs"(代码如下) using System.Collections; using System.Collections.Generic; using Unity

  • Unity3D旧电视滤镜shader的实现示例

    实现思路 既然是要实现旧电视的后处理效果,那么只要回忆一下那些古旧的电视的显示效果然后进行模拟就可以了. 1.首先那种大头电视一般屏幕有一些曲率,并不是完全的一个平面,而且一般是向外凸起,这种凸起会造成中间的显示区域会比原来更近一些,边缘的显示区域会比原来更远一些.这种效果我们直接用简单的二次函数来实现. 2.那种老旧电视会有不断运动的噪声,我们直接使用噪声函数加上时间变量来实现. 3.屏幕上会有一些条纹效果,这种周期性的条纹效果一般用三角函数来实现. 当然不可能模拟的完全准确..也没有完全准确

  • 详解Unity入门之GameObject

    GameObject和Component GameObject是游戏场景中真实存在的,而且有位置的一个物件 Component附属于GameObject,控制GameObject的各种属性 GameObject是由Component组合成的,Component的生命周期和GameObject息息相关.调用此GameObject的Destroy方法,它的子对象和对应的所有Component都会被销毁,但也可以一次只销毁一个Component 常见的Component: Component 作用 R

  • Unity给物体添加多个Tag的实现

    在unity中,我们经常通过给物体添加标签来判断这个物体是不是我们想要的 但是unity默认只能添加一个标签,那如果我们要给一个物体添加多个标签应该怎么办 首先,我们定义一个Tag.cs类,这个类用来存储物体的tag信息 public class Tags : MonoBehaviour{ public List<string> tags=new List<string>(); } 然后创建一个单例类TagManager.cs用来管理tag public class TagMana

  • Unity实现瞄准镜效果

    本文实例为大家分享了Unity实现瞄准镜效果的具体代码,供大家参考,具体内容如下 using UnityEngine; using System.Collections; public class TelesopicView : MonoBehaviour { public float zoomLevel = 2.0f; public float zoomInSpeed = 100.0f; public float zoomOutSpeed = 100.0f; private float ini

  • 详解Unity使用ParticleSystem粒子系统模拟药水在血管中流动(粒子碰撞)

    一.前言 点关注不迷路,持续输出Unity干货文章. 嗨,大家好,我是新发. 之前我写了一篇Unity流体模拟的文章:<Unity流体模拟,支持粒子系统,支持流体碰撞交互(Obi Fluid插件使用教程)> 然后有同学私信我,问我能否做药剂打入血管的效果. 这个嘛,用ObiFluid可以做,不过我今天要尝试的,是用另一种方式:直接使用Unity的粒子系统来做. 二.最终效果 最终效果如下,效果虽然一般,不过制相对简单很多. 本文Demo工程已上传到CodeChina,感兴趣的同学可自行下载学习

  • Unity实现3D射箭小游戏

    Unity 小游戏:3D射箭,供大家参考,具体内容如下 前两周因为实训太忙,再加上自己对老师所讲的设计模式并不是很理解,所以就没有写博客.这次博客是记录3D射箭游戏的实现过程. 1. 准备资源 我是在网上找的弓与箭的资源,至于靶子,创建五个不同大小的同心圆柱体,如图所示: 需要注意的是,五个圆柱体并不在同一个平面上,这样才能够看清每一环的颜色,并且在检测碰撞时不会出现各种问题. 另外,如果靶子放得离相机太近,就没有射箭的感觉了:离相机太远,好像又看不清靶子了,然后我试着把靶子Material的S

  • 基于Unity3D实现3D迷宫小游戏的示例代码

    目录 一.前言 二.构思 三.正式开发 3-1.搭建场景 3-2.设置出入口 3-3.添加角色 3-4.实现角色移动 3-5.出入口逻辑 四.总结 一.前言 闲来无事,从零开始整个<3D迷宫>小游戏. 本篇文章会详细介绍构思.实现思路,希望可以帮助到有缘人. 二.构思 首先,要实现一个小游戏,心里肯定要有一个大概的想法,然后就是将想法完善起来. 我的想法就是一个用立体的墙搭建的迷宫,然后控制人物在迷宫中移动,最后找到出口,就这么简单. 当然,这是一个雏形,比如可以加点音效.背景.关卡.解密等.

  • 七夕情人节丘比特射箭小游戏

    载入jQuery <script src="./jquery-1.11.0.min.js" type="text/javascript"></script> HTML <div class="rank"> <div class="bangdan">勇士榜</div> <ul> <li>鲁大师 成功射中!</li> <li>

  • Unity实战之FlyPin(见缝插针)小游戏的实现

    目录 一.简单介绍 二.FlyPin (见缝插针)游戏内容与操作 三.游戏代码框架 四.知识点 五.游戏效果预览 六.实现步骤 七.工程源码地址 八.延伸扩展 一.简单介绍 Unity 游戏实例开发集合,使用简单易懂的方式,讲解常见游戏的开发实现过程,方便后期类似游戏开发的借鉴和复用. 本节介绍,FlyPin (见缝插针) 休闲小游戏快速实现的方法,希望能帮到你,若有不对,请留言. 二.FlyPin (见缝插针)游戏内容与操作 1.游戏开始,针 Pin 自动准备好, 2.鼠标点击左键发射 Pin

  • Unity实现见缝插针小游戏

    本文实例为大家分享了Unity实现见缝插针游戏的具体代码,供大家参考,具体内容如下 控制小球旋转 using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateSelf : MonoBehaviour { //每秒旋转90度 public float speed = 90; // Update is called once per frame void Updat

  • 利用Matlab制作一款3D版2048小游戏

    其实逻辑和2维版本完全一样,就不进行详细解说了,直接看效果: 效果: 目前界面还不咋好看,期待大家的优化 还是键盘↑↓←→操作嗷 完整代码: function game20483D global squaremap global colorlist global fontsizelist global baseX baseY baseZ global barHdl textHdl global txtBest txtScore global best fig=figure('units','pi

  • Unity游戏开发之射击小游戏的实现

    目录 前言 游戏画面展示 游戏代码解析 游戏打包 总结 前言 人们一直都说学习和玩游戏不能兼顾,那我们就来边学习怎样制作游戏,边玩游戏 不就兼得了嘛~ 我可真是一个小天才呢~ 所以本篇文章为大家带来一个 横版2D射击小游戏,游戏制作超级简单,玩法一学就会, 一起来看看吧! 游戏画面展示 这款小游戏只用了两个UI界面,一个是菜单界面,另一个是战斗界面 菜单界面有三种模式,分别是一般.困难和地狱 战斗界面就是很简单的从两边刷野怪,然后主角开枪打死他们 UI搭建很简单,只有一张背景图使用Image,加

  • Three.js+React实现3D开放世界小游戏

    目录 背景 效果 设计 实现 加载资源 页面结构 数据初始化 场景初始化 创建世界 创建星空 创建地形 加载进度管理 创建基地模型 创建阿狸模型 控制阿狸运动 动画更新 页面缩放适配 添加游戏逻辑 毛玻璃效果 总结 背景 2545光年之外的开普勒1028星系,有一颗色彩斑斓的宜居星球 ,星际移民必须穿戴基地发放的防辐射服才能生存.阿狸驾驶星际飞行器降临此地,快帮它在限定时间内使用轮盘移动找到基地获取防辐射服吧! 本文使用 Three.js + React + CANNON 技术栈,实现通过滑动屏

  • 基于Matlab制作伪3D第一视角迷宫小游戏

    目录 游戏效果 游戏原理说明 第一代程序计算交点方法 第二代程序计算交点方法 距离转换为线段长度 完整代码 游戏效果 使用键盘上方向键↑向前移动 使用键盘左右方向键调整← →朝向 游戏原理说明 原理很简单,如效果图所示,主要就是以角色视角方向发射大量的直线模拟视线,并计算直线与墙壁交点,获取每一条视线方向下,角色到墙壁的距离,然后根据近大远小的原理绘制不同长度的竖向直线模拟墙壁. 第一代程序计算交点方法 第一代程序是使用的polyshape对象(二维多边形对象)制作墙壁,polyshape对象重

  • Unity实现3D贪吃蛇的移动代码

    本文实例为大家分享了Unity实现3D贪吃蛇移动的具体代码,供大家参考,具体内容如下 记录一下前段时间写到的一个3D贪吃蛇的移动代码. 链接:Unity实现3D贪吃蛇 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GameManager : MonoBehaviour { List<Transform> bodyL

随机推荐