Unity密室逃脱制作 C#

首先创建一个项目

进入场景后

 导入资源场景scene

 

 创建一个资源包Resources

 在Resources包下创建子包Meshs

将场景scene拖至Meshs包下

再将Materials拖拽至Resources包下

 将texture改名为Textures

之后将场景拖拽至场景中

 

 在材质包Materials下全选所有物体ctrl + a

在右侧Inspector属性面板下修改着色器Shader

修改为Autodesk Interavtive

点击场景 勾选右侧static静态

 在Textures包下创建子包HDR

点击Assets将hdr和moonless移至HDR子包下

在HDR子包下创建一个材质

首先看一下hdr右侧Inspector属性面板下存放位置,我们看到了在Cubemap下

 然后我们点击材质点击Shader搜索Cubemap

这时候我们看到下面的右侧有个槽,我们将hdr点击进去

我们运行项目会发现房屋里面出现很多白色,造成这种原因是光线太强了, 我们需要在场景中找到所有光源物体选中后调节至1

 

接下来Meshs子包下 导入角色资源

 将T-Pose拖拽至场景中

 我门发现房子的墙壁使白色的

我们在Materials子包下找到墙壁

 看右侧属性面板

在点击Textures子包下找到墙壁发现有四个贴图

 将贴图拖拽至右侧属性栏中

点击渲染灯光

搜索添加hdr后场景更改为

 Hierarchy面板下选择Type

搜索MeshRenderer

 全选物体添加碰撞器

 

在场景中添加一个组件Light

修改其属性面板

 在Character子包下创建Animator Controller动画控制器

 修改名字为PlayerCotroller并且点击

将Standing拖拽至动画器中并且改名为Idle

 再将以下三个动画器添加并且依次命名

 

接下来创建连线

在Parameters下添加bool

添加以下变量

 设置连线

 给人物配置着色

接下来对角色完全解压缩

 将角色拖拽至预制体后删掉,并修改人物名字Player

 

 之后再拖回场景中

 取消掉所有动画器连线的 has

将主摄像机放在Player下并归零坐标

创建脚本

添加一下代码

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


public static class AnimatorList
{
    public static int IsIdle = Animator.StringToHash("isIdle");
    public static int IsWalk = Animator.StringToHash("isWalk");
    public static int IsRun = Animator.StringToHash("isRun");
    public static int IsDying = Animator.StringToHash("isDying");
}

public class Player : MonoBehaviour
{
    private CharacterController _characterController;
    private Animator _animator;

    public int health = 100;

    public float velocity = 0.5f;

    private void Awake()
    {
        _characterController = GetComponent<CharacterController>();
        _animator = GetComponent<Animator>();
    }

    void Start()
    {
        _animator.SetBool(AnimatorList.IsIdle, true);
    }

    void Update()
    {
        Move();
        MoveByAnimation();
    }

    private void Move()
    {
        var vertical = transform.forward * Input.GetAxis("Vertical") * velocity * Time.deltaTime;
        var horizontal = transform.right * Input.GetAxis("Horizontal") * velocity * Time.deltaTime;

        Vector3 gravity = Vector3.zero;

        if (!_characterController.isGrounded)
            gravity = transform.up * -9.8f * Time.deltaTime;

        _characterController.Move(horizontal + vertical + gravity);
    }

    private void MoveByAnimation()
    {
        if(!_animator.GetBool(AnimatorList.IsWalk) && !_animator.GetBool(AnimatorList.IsRun))
        {
            _animator.SetBool(AnimatorList.IsIdle, true);
        }

        if(Input.GetAxis("Vertical") != 0 && !_animator.GetBool(AnimatorList.IsRun))
        {
            _animator.SetBool(AnimatorList.IsIdle, false);
            _animator.SetBool(AnimatorList.IsWalk, true);
            _animator.SetFloat("velocity", Input.GetAxis("Vertical"));
        }

        if (_animator.GetFloat("velocity") < 0.2f)
        {
            _animator.SetBool(AnimatorList.IsIdle, true);
            _animator.SetBool(AnimatorList.IsWalk, false);
            _animator.SetBool(AnimatorList.IsRun, false);
        }

        if (Input.GetKeyDown(KeyCode.LeftShift))
        {
            _animator.SetBool(AnimatorList.IsIdle, false);
            _animator.SetBool(AnimatorList.IsWalk, false);
            _animator.SetBool(AnimatorList.IsRun, true);
        }

        if (Input.GetKeyUp(KeyCode.LeftShift))
        {
            _animator.SetBool(AnimatorList.IsRun, false);
        }
    }
}
创建脚本

添加一下代码

using UnityEngine;

namespace InstanceClasses.GamePlay
{
    public class MouseController : MonoBehaviour 
    {
        public Transform playerBody;

        public float mouseSensitivity = 100f;

        public float xRotation;

        private void Start()
        {
            playerBody = transform.parent;
            Cursor.lockState = CursorLockMode.Locked;
        }

        private void FixedUpdate()
        {
            float mouseX = Input.GetAxis("Mouse X") * Time.deltaTime * mouseSensitivity;
            float mouseY = Input.GetAxis("Mouse Y") * Time.deltaTime * mouseSensitivity;

            xRotation -= mouseY;
            xRotation = Mathf.Clamp(xRotation, -90, 90);

            transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
            playerBody.Rotate(Vector3.up, mouseX);

            playerBody.localRotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0);
        }

    }
}

 接下来代码绑定

将动画器放至

 

在场景中找到所有光源

调节面板属性

  

 目前可以完成通过键盘方向键和鼠标场景移动转换视角

接下来我们为屏幕设计一个UI目标点,为了拾取道具

首先创建一个UI的Canvas

 再在Canvals下创建一个Panal

 点击Game界面

 修改Pannal名为HUDPannal

 

再在HUDPannal下创建一个Image中心点

 将中心方块改成中心点

 修改颜色

 修改大小

 在HUDPannal下再创建个Pannal

 修改Pannal为PlayerInformation

 

修改PlayerInformation,点击PlayerInformation,再点击右侧瞄点

修改属性面板

点击左侧

将左上角设置为零点

 再调节x,y的位置让面板在左上角全部显示出来

再次创建

在创建slider作为血条

 添加一个水平分化

 修改对齐方式

修改血条长度

 再次创建Image修改Image形状

修改名称

给Mask图像添加Mask组件

 修改Mask形状即可修改

修改血条颜色将空白设置为白色或者粉色

 接下来点填充颜色设置为红色

回到slider就可以调节血量了

修改血量最大值

 修改名字

删除PlayerInformation组件里的Image

再删除HUDPannal里的Image

可以看到Pannal消失了

 接下来我们整理代码文件,

将以下代码存放在新建的GamePlays下 

 再新建文件夹

 在UIPannals文件夹下新建脚本文件HUDPanel

将以下代码复制

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

public class HUDPanel : MonoBehaviour
{
    public Image Icon;

    public Slider Health;

    public Player player;

    private void Start()
    {
        var playerObj = GameObject.FindGameObjectWithTag("Player");
        player = playerObj.GetComponent<Player>();

        Icon.sprite = Resources.Load<Sprite>("Textures/UITexture/ActorIcon");
    }

    // Update is called once per frame
    void Update()
    {
        if (Health != null)
            Health.value = player.health;
    }
}
将对象绑定在脚本文件上

最后将Player对象Tag标签设置成Player

 创建UITexture文件包存放UI头像

将头像拖拽至UITexture文件中

将图片设置为可变精灵

 拖拽即可完成头像设置

将Textures拖拽至Resources包下并查看路径是否与

HUDPannal代码是否相同

运行即可完成

将场景中一块物体ctrl + d并且移动至指定地点设置为陷阱

移除该物体本身碰撞器

 

添加Box Collider

创建一个脚本文件夹存放陷阱

 在文件夹中创建脚本文件Trap_1

将以下代码复制

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;

public class Trap : MonoBehaviour
{
    public GameObject arrowPrefab;
    private GameObject[] arrowPoints = new GameObject[6];
    private bool isActive;
    private void Start()
    {
        int sub = 0;
        foreach (var point in transform.Find("Trap/knifePoint").GetComponentsInChildren<Transform>())
        {
            {
                if (transform != point)
                {
                    arrowPoints[sub] = point.gameObject;
                    sub++;
                }
            }
        }


    }
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            Debug.Log("Running");
            for (int i = 0; i < 5; i++)
            {
                Instantiate(arrowPrefab, arrowPoints[i].transform.position + new Vector3(0, 0.5f, 0), Quaternion.identity);
            }
            isActive = true;
        }
    }

}

注意代码中

 注意:查找只能从子物体开始找 

将XJ_1名改为Trap 

给Trap添加一个空的父物体

将Trap的Box Collider去掉

 挂载到GameObject父物体上

清零父物体

设置碰撞器大小

 创建粒子特效

其面板可修改

在爱给网或者cgmodel.com下载fbx图片粘贴在Meshs下

将刀拖拽至场景中

并移动位置

修改刀名字为knife

将knife放进预制体后在场景中删除

 调节刀的属性面板将刀旋转180°修改位置后完全解压缩

再创建子物体

依次创建

 

  给制体添加一个Mesh Collider

打开触发器的isTrigger

 取消Trap属性面板的Contribute Globall lll

运行即可走到触发器附近触发触发器

接下来用一种简单方式发生粒子碰撞使角色扣血

首先创建一个粒子

右侧属性面板开启 

  

接着创建一个c#脚本DesPlay

 

 代码如下

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

public class DesPlay : MonoBehaviour
{
    public Player player;


    private void OnParticleCollision(GameObject other)
    {
        Debug.Log("粒子发生碰撞");
        if (other.gameObject.tag == "Player")
        {
            Debug.Log("粒子碰撞玩家");
            player.health -= 1f;
        }
       if(player.health == 0)
           Destroy(other.gameObject);
    }
}
 


将代码绑定在粒子上

将player对象绑定至DesPlayer脚本上

运行

陷阱制作完成,接下来做取钥匙开门,逃脱 

首先我们再爱给网上下载一个钥匙的fbx资源

 之后拖进场景摆放该位置

 完全解压缩

添加碰撞器

开启isTrigger

 在创建c#脚本BoxKey

将以下代码复制

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

public class BoxKey : MonoBehaviour
{
    public int id;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

将BoxKey标签改成Item

 将Player代码修改成
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Scripting.APIUpdating;
public static class AnimatorList
{

    public static int IsIdle = Animator.StringToHash("isIdle");
    public static int IsWalk = Animator.StringToHash("isWalk");
    public static int IsRun = Animator.StringToHash("isRun");
    public static int IsDying = Animator.StringToHash("isDying");
}

public class Player : MonoBehaviour
{
    public GameObject winPanel;

    private CharacterController _characterController;
    private Animator _animator;
    public float velocity = 3f;
    public float health = 100;
    public int package = 0;
    public int condition = 10;

    private void Awake()
    {

        _characterController = GetComponent<CharacterController>();
        _animator = GetComponent<Animator>();
    }


    void Start()
    {
        _animator.SetBool(AnimatorList.IsIdle, true);
    }


    void Update()
    {
        Move();
        MoveByAnimation();
        PickUpItem();
        OpenDoor();
    }
    private void Move()
    {
        var vertical = transform.forward * Input.GetAxis("Vertical") * velocity * Time.deltaTime;
        var horizontal = transform.right * Input.GetAxis("Horizontal") * velocity * Time.deltaTime;
        Vector3 gravity = Vector3.zero;
        if (!_characterController.isGrounded)
            gravity = transform.up * -9.8f;

        _characterController.Move(horizontal + vertical + gravity);
        /*Vector3 moveVector;   
        Vector3 moveVector;
        moveVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
       
        Vector3 gravity = Vector3.zero;
        if (!_characterController.isGrounded)
            gravity = transform.up * 9.8f;
        moveVector += gravity;
        moveVector *= Time.deltaTime;
        _characterController.Move(moveVector);*/
    }
    //计算移动方向
    private void MoveByAnimation()
    {
        if (!_animator.GetBool(AnimatorList.IsWalk) && !_animator.GetBool(AnimatorList.IsRun))
        {
            _animator.SetBool(AnimatorList.IsIdle, true);
        }
        if (Input.GetAxis("Vertical") != 0 && !_animator.GetBool(AnimatorList.IsRun))
        {
            _animator.SetBool(AnimatorList.IsIdle, false);
            _animator.SetBool(AnimatorList.IsWalk, true);
            _animator.SetFloat("velocity", Input.GetAxis("Vertical"));

        }
        if (_animator.GetFloat("velocity") < 0.2f)
        {
            _animator.SetBool(AnimatorList.IsIdle, true);
            _animator.SetBool(AnimatorList.IsWalk, false);
            _animator.SetBool(AnimatorList.IsRun, false);
        }
        if (Input.GetKeyDown(KeyCode.LeftShift))
        {
            _animator.SetBool(AnimatorList.IsIdle, false);
            _animator.SetBool(AnimatorList.IsWalk, false);
            _animator.SetBool(AnimatorList.IsRun, true);
        }
        if (Input.GetKeyDown(KeyCode.LeftShift))
        {

            _animator.SetBool(AnimatorList.IsRun, false);
        }
    }
    public void OpenDoor()
    {
        if (Input.GetKeyUp(KeyCode.E))
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out var hit))
            {
                if (hit.collider.CompareTag("Door"))
                {
                    if (package == condition && package != 0)
                    {


                        winPanel.SetActive(true);
                        //    Time.timeScale = 0.1f;
                        StartCoroutine(OnGameEnd());
                    }
                    //胜利
                }
            }
        }
    }
    public void PickUpItem()
    {
        if (Input.GetKeyUp(KeyCode.E))
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out var hit))
            {
                if (hit.collider.CompareTag("Item"))
                {
                    package += hit.collider.GetComponent<BoxKey>().id;
                    Destroy(hit.collider.gameObject);
                }
            }
        }
    }

    public IEnumerator OnGameEnd()
    {
        yield return new WaitForSeconds(3);
        SceneManager.LoadScene("界面");
    }
}

之后将代码绑定在BoxKey上

运行即可拾取药匙

对准箱子,按E后,Package从0 变成 1 ,物品消失 

 药匙制作完成,

接下来我们制作触碰门就显示胜利界面

首先选中门,设置Tag为Door

接下来我们在Canvas下再创建个Panel

 

起名为WinPanel

再在Panel面板上创建文字

 将WinPanel面板藏起来

将WinPanel绑定在Player脚本对象上

 运行即可跑通游戏 

 按E拾取宝箱后面向门按E即可胜利

 最后我们添加一个入口场景界面

进入入口场景

创建Pannel后,下载界面资源,存到Textures包下

将图片设置为精灵Sprite

拖拽至Panel下,调节颜色与透明度 在Panel面板下创建一个V L Group,使上下分两个面板水平分布

 

在Panel下再创建两个Panel

将两个Panel都设置成1920 * 540

修改三个Panel名字 

 

 在LogoPanel下创建个Image

 在网上下载Logo图片

使用精灵存放在Image中,并且调节Image大小颜色,透明度

修改居中

 接下来创建一个按钮

 修改颜色框框改灰色,字体改白色

创建两个shadow

 修改值和颜色

 创建一个c#脚本Button 

将以下代码复制

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

public class Butten : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    public Shadow[] shadows;
    public Vector2[] shadowDrigin;
    public void OnPointerEnter(PointerEventData eventData)
    {
        foreach (var shadow in shadows)
        {
            shadow.effectDistance = new Vector2();
        }
    }
    public void OnPointerExit(PointerEventData eventData)
    {
        int sub = 0;
        foreach (var shadow in shadows)
        {
            shadow.effectDistance = shadowDrigin[sub];
            sub++;
        }
    }
    private void Start()
    {
        shadows = GetComponents<Shadow>();
        shadowDrigin = new Vector2[shadows.Length];
        int sub = 0;
        foreach (Shadow shadow in shadows)
        {
            shadowDrigin[sub] = shadow.effectDistance;
            sub++;
        }
    }

}
将Button代码绑定在Button上

即可完成运行后阴影效果

将Button拽成预制体

最后将两个Panel下的Image隐藏或者移除组件

创建一个c#脚本MainMenuPanel

将以下代码复制

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

public class MainMenuPanel : MonoBehaviour
{
    private Transform _buttonPanel;

    private Button StartButton;
    private Button ExitButton;

    private void Start()
    {
        _buttonPanel = transform.Find("ButtonPanel");

        StartButton = _buttonPanel.Find("Button").GetComponent<Button>();
        //ExitButton = _buttonPanel.Find("ExitGame_btn").GetComponent<Button>();

        StartButton.onClick.AddListener(() => { SceneManager.LoadScene("SampleScene"); });
        //ExitButton.onClick.AddListener(() => { Application.Quit(); });

    }
}

 将代码绑定在MainMenuPanel

接下来游戏打包

按照次序存放两个场景点击buding即可打包游戏

猜你喜欢

转载自blog.csdn.net/weixin_69360830/article/details/131096957