unity射箭游戏

本文详细介绍了开发一款包含地形、天空盒、固定靶和运动靶的第一人称射箭游戏的过程,涉及玩家视角控制、移动、蓄力射击机制、碰撞检测以及记分系统。
摘要由CSDN通过智能技术生成

开发第一人称射箭游戏

游戏要求:

  • 地形:使用地形组件,上面有草、树;
  •  天空盒:使用天空盒,天空可随玩家位置 或 时间变化 或 按特定按键切换天空盒;
  •  固定靶:有一个以上固定的靶标;
  •  运动靶:有一个以上运动靶标,运动轨迹,速度使用动画控制;
  •  射击位:地图上应标记若干射击位,仅在射击位附近可以拉弓射击,每个位置有 n 次机会;
  •  驽弓动画:支持蓄力半拉弓,然后 hold,择机 shoot;
  •  游走:玩家的驽弓可在地图上游走,不能碰上树和靶标等障碍;
  •  碰撞与计分:在射击位,射中靶标的相应分数,规则自定;                                                   

游戏效果图:

游戏编程文件如下:

一、实现玩家走动和转动视角

通过CameraMgr和CrossbowMove来实现视角的转动

CameraMgr

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

public class CameraMgr : MonoBehaviour
{
    //鼠标x轴灵敏度
    public float mouseXSensitivity = 80f;
    //人物
    private Transform player;
    //旋转角度
    float xRotation = 0f;

    public bool isMove;
    private void Start()
    {
        player = transform.parent.transform;
        isMove = true;
    }


    // Update is called once per frame
    void Update()
    {
        if (isMove)
        {
            float mouseX = Input.GetAxis("Mouse X") * mouseXSensitivity * Time.deltaTime;
            float mouseY = Input.GetAxis("Mouse Y") * mouseXSensitivity * Time.deltaTime;
            xRotation -= mouseY;
            //y轴最大旋转角度为正负90;
            xRotation = Mathf.Clamp(xRotation, -45f, 10f);
            transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
            player.Rotate(Vector3.up * mouseX);
        } 
    }
}

CrossbowMove

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

public class CrossbowMove : MonoBehaviour
{
    //人物控制器
    private CharacterController controller;
    //人物移动速度
    public float speed = 2f;
    public float gravity = -15f;
    Vector3 velocity;
    //是否可以移动摄像机
    bool isMove;

    private CameraMgr cameraMgr;

    private void Start()
    {
        controller = GetComponent<CharacterController>();
        cameraMgr = transform.GetChild(0).GetComponent<CameraMgr>();
        isMove = true;
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    // Update is called once per frame
    void Update()
    {
        //按键Q隐藏 或者显示鼠标
        if (Input.GetKeyDown(KeyCode.Q))
        {
            isMove = !isMove;
            isMove = cameraMgr.isMove;
            if (isMove == false)
            {
                Cursor.lockState = CursorLockMode.None;
                Cursor.visible = true;
            }
        }
        if (isMove)
        {
            Move();
        }
    }

    //移动
    public void Move()
    {
        //键盘输入
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Vector3 move = transform.right * x + transform.forward * z;
        controller.Move(move * speed * Time.deltaTime);
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }


}

二、弩的射击与蓄力实现

弩的射击通过CrossbowMgr来进行管理,蓄力的逻辑根据按鼠标左键时长来确定。

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

public class CrossbowMgr : MonoBehaviour
{
    Animator anim;
    //蓄力时间
    float downTime;
    //飞行的力
    float arrowForce;
    //是否蓄力
    bool isEnergyStorage;
    //箭预制体
    public GameObject arrowPrefab;
    //发射点
    public Transform firePoint;

    public RawImage arrowCameraRawImg;

    public bool isFire;
    //是否在发射点
    public bool isFirePos;

    public FiringPosition firingPosition;

    public GameObject firingPosText;

    public GameObject gameOver;

    void Start()
    {
        anim = GetComponent<Animator>();
        isEnergyStorage = true;
    }

    void Update()
    {
        if (isFire)
        {
            //蓄力功能
            if (isEnergyStorage)
            {   //蓄力阶段按下鼠标左键
                if (Input.GetMouseButtonDown(0))
                {
                    //进入蓄力动画
                    arrowCameraRawImg.enabled = false;
                    anim.SetTrigger("hold");
                }//鼠标按下阶段
                else if (Input.GetMouseButton(0))
                {
                    //计算蓄力时间
                    downTime += Time.deltaTime;
                    //设置蓄力动画
                    anim.SetFloat("hold_power", downTime);
                }//鼠标抬起阶段
                else if (Input.GetMouseButtonUp(0))
                {
                    //蓄力取消
                    isEnergyStorage = false;
                    //为飞行的力赋值
                    arrowForce = downTime;
                    //清空蓄力时间
                    downTime = 0;
                }
            }
            else//发射功能
            {   //蓄力完成发射
                if (Input.GetMouseButtonUp(0))
                {
                    //播放动画
                    anim.SetTrigger("shoot");
                    //设置可以重新蓄力
                    isEnergyStorage = true;
                    //清空所有箭
                    ResetArrow();
                    //发射弩箭
                    FireArrow();
                }
            }
        } 
    }
    
    //弩箭发射
    public void FireArrow()
    {
        firingPosition.count--;
        firingPosText.transform.GetComponent<Text>().text = "当前位置还可以发射次数为:" + firingPosition.count.ToString();
        //实例化箭
        GameObject arrow = Instantiate(arrowPrefab, firePoint.position, firePoint.rotation);
        //获得刚体
        Rigidbody arrowRigidbody = arrow.GetComponent<Rigidbody>();
        //根据蓄力大小发射弩箭
        arrowRigidbody.velocity = transform.forward * arrowForce * 30f;

        Invoke("AllFirePosCount", 3f);
    }


    public void ResetArrow()
    {
       var arrowObjs = GameObject.FindGameObjectsWithTag("Arrow");

        for (int i = 0; i < arrowObjs.Length; i++)
        {
            Destroy(arrowObjs[i]);
        }
    }

    /// <summary>
    /// 检测全部靶子是否可以发射
    /// </summary>
    public void AllFirePosCount()
    {
        var firePosObjs = GameObject.FindGameObjectsWithTag("FirePos");
        int tempInt = 0;
        for (int i = 0; i < firePosObjs.Length; i++)
        {
            if (firePosObjs[i].transform.GetComponent<FiringPosition>().count <= 0)
            {
                tempInt++;
            }
        }
        if (tempInt >= 5)
        {
            gameOver.SetActive(true);
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
        }
    }
}

实现弩蓄力的动画如下:

其中new hold为混合树

三、地形

使用的资源包为tree9,绘制好地形和树,加入墙体,并手动为预制件添加组件“Capsule Collider”,以增加碰撞体。

四、靶的制作

游戏共有三个固定靶,两个移动靶,为运动靶添加动画。通过窗口->动画->动画打开动画编辑器。选中运动靶游戏对象->选择添加动画->添加运动靶的位置属性->设置三个关键帧,初始帧坐标为(0,0,0),末尾帧的位置坐标和初始帧相同。然后创建动画控制器,设置如下动画转移:

五、天空盒

使用Fantasy Sky FREE的天空素材。当按下f1时切换。

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

//设置天空盒
public class SetSkyBox : MonoBehaviour
{
    public Material[] skyMaterials;
    private Skybox skybox;
    int index;

    void Start()
    {
        //获取组件
        skybox = GetComponent<Skybox>();
        //设置材质
        skybox.material = skyMaterials[index];
    }

     void Update()
    {
        if (Input.GetKeyDown(KeyCode.F1))
        {
            SetMaterial();
        }
    }
    //设置天空盒
    public void SetMaterial()
    {
        index++;
        if (index >= skyMaterials.Length)
        {
            index = 0;
        }
        skybox.material = skyMaterials[index];
    }
}
六、记分

        根据射到靶的不同位置进行计分,右上角会显示总的分数,当每个位置的箭都用完后,提示重新开始。

视频地址:unity射箭游戏-其他-高清完整正版视频在线观看-优酷 (youku.com)

代码地址:3d-game/w11/Reset at main · wujf37/3d-game (github.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值