Unity之创建第一个2D游戏项目

news2025/1/19 8:14:26

一 Unity环境配置

1.1 Untity资源官网下载:https://unity.cn/releases

7809e26a5c1f45e49d0a972fde264483.png

1.2 Unity Hub集成环境,包含工具和项目的管理

ee8bd7d92b3443aba065134e51b97fcc.png

1.3 Unity Editor编辑器

a5afe3362d9d48d1be137de76d1cedaa.png1.4 Visual Studio 2022脚本编辑器

d8ad8983dc964e4cac255e34973cca83.png

1.5 AndroidSKD,JDK,NDK工具,用于android环境的运行

7043b3c77f664511a052ac60f28c06d6.png

二 创建Unity项目

2.1 新建2D模板项目211d66aca7eb4c96850de94c176e3c8a.png

d74e22e6c2d6428492cc0af1149f9e40.png

2.2 新建2D物体

146964934d02462c9e3ccdadb34d4c8e.png

2.3 新建C#脚本文件 

595d8433b82543e0bdef2e9602ea282a.png

2.4 脚本文件拖拽到物理区域,关联物体 

ca6d8b0a44ff4953a9b4a27bd77b0480.png

2.5 点击脚本打开 Visual Studio 进行编辑

a789d84939034ac4a4dc7736b5ee1f9e.png

2.6 输入Debug.Log(gameObject.name);获取物体的名字,点击运行 

f55a21616dec4cd5b92fc8347c3cd3bb.png

2.7 调试 ,脚本文件保存后,可以看到UnityEditor里面的脚本文件会同步变化

cf9c057fc4424d07bec360f46632273f.png

2.9 点击顶部运行按钮就可以在控制台看到日志输出信息,可以看到打印出了物理对象的名字和标签

4b19bc14f8d6475cae98e3fef977c9a4.png

三 运行问题

3.1 第一次运行可能会出现错误,显示Unity脚本显示“杂项文件”,并且无语法提示的问题

73a154711a974aa48ab4ff15e690e55d.png

3.2  解决方法:点击 编辑(Edit)>首选项(Preferences)打开首选项窗口 

e2c639fdb0264ead81f6b134c7aec7ee.png

3.3 在首选项窗口中,选择 外部工具(External Tools)选项卡,将 外部脚本编辑器(External Script Editor)的设置改为 Visual Studio 2019等编辑器 b5372929d89d4cb98ef0deee76e289d0.png

3.4 可以看到语法能够正常显示了 

808c68efbbad43668fb3b1d4a373aea0.png

四,物体组件认识

4.1  一个物理有很多组件,点击物理,默认组件信息就会出来

fc756b5b0e644826a4689bd6f369bc29.png

4.2 如下可以给物理新加组件信息,比如给物体新加声音组件

099b6ceb991b4c6196f34f8763afcc6a.png

4.3 脚本关联物体后,也也属于物体的一个组件 ,可以在脚本中获取物体的其它组件和控制物体的组件

36238f326f914a3e9e040eea9a29feb6.png

4.4  物体下面还可以创建多个物体,我们创建一个胶囊子物体,那胶囊就属于子组件

012ea1cff2ec4240a7483fe37a584bba.png

4.5 脚本获取基础组件和子组件,父组件。如下获取物体和组件实例:

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

public class main : MonoBehaviour
{
    public GameObject Capsule;//胶囊组件
    public GameObject Prefab;//预设体
    // Start is called before the first frame update
    void Start()
    {

        //拿到当前脚本所挂载的游戏物体
        //GameObject go = this.gameObject;
        //名称
        UnityEngine.Debug.Log(gameObject.name);
        //tag
        UnityEngine.Debug.Log(gameObject.tag);
        //layer
        UnityEngine.Debug.Log(gameObject.layer);

        //胶囊的名称
        UnityEngine.Debug.Log(Capsule.name);
        //胶囊当前真正的激活状态
        UnityEngine.Debug.Log(Capsule.activeInHierarchy);
        //胶囊当前自身激活状态
        UnityEngine.Debug.Log(Capsule.activeSelf);

        //获取Transform组件
        //Transform trans = this.transform;
        UnityEngine.Debug.Log(transform.position);

        //获取其他组件
        BoxCollider bc = GetComponent<BoxCollider>();
        //获取当前物体的子物体身上的某个组件
        GetComponentInChildren<CapsuleCollider>(bc);
        //获取当前物体的父物体身上的某个组件
        GetComponentInParent<BoxCollider>();
        //添加一个组件
        Capsule.AddComponent<AudioSource();
        //通过游戏物体的名称来获取游戏物体
        //GameObject test = GameObject.Find("Test");
        //通过游戏标签来获取游戏物体
        GameObject test = GameObject.FindWithTag("Enemy");
        test.SetActive(false);
        UnityEngine.Debug.Log(test.name);
        //通过预设体来实例化一个游戏物体
        GameObject go = Instantiate(Prefab, Vector3.zero, Quaternion.identity);
        //销毁
        Destroy(go);
    }

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

五 鼠标和触摸事件

5.1 鼠标事件

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.Windows;
using Input = UnityEngine.Input;

public class main : MonoBehaviour
{

    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        //鼠标的点击
        //按下鼠标 0左键 1右键 2滚轮
        if (Input.GetMouseButtonDown(0)){
            UnityEngine.Debug.Log("按下了鼠标左键");
        }
        //持续按下鼠标
        if (Input.GetMouseButton(0)) {
        UnityEngine.Debug.Log("持续按下鼠标左键");
        }
        //抬起鼠标
       if (Input.GetMouseButtonUp(0)) {
            UnityEngine.Debug.Log("抬起了鼠标左键");
        //按下键盘按键
        }
        if (Input.GetKeyDown(KeyCode.A)) {
            UnityEngine.Debug.Log("按下了A");
                }
        //持续按下按键
        if (Input.GetKey(KeyCode.A)) {
            UnityEngine.Debug.Log("持续按下A");
         }
        //抬起键盘按键
        if (Input.GetKeyUp("a")){
           UnityEngine.Debug.Log("松开了A");
        }
    }
}

5.2 保存运行后可以看到控制台有对应的日志输出

0033d5d5031041c990b03baf295cc152.png

5.3 手机单点,多点触控、

using UnityEngine;
using Input = UnityEngine.Input;

public class main : MonoBehaviour
{

    void Start()
    {
        //开启多点触控
        Input.multiTouchEnabled = true;
    }

    // Update is called once per frame
    void Update()
    {
        //判断单点触摸
        if (Input.touchCount == 1)
        {
            //触摸对象
            Touch touch = Input.touches[0];//触摸位置
            UnityEngine.Debug.Log(touch.position);//触摸阶段
            switch (touch.phase)
            {
                case UnityEngine.TouchPhase.Began:

                    break;
                case UnityEngine.TouchPhase.Moved:

                    break;
                case UnityEngine.TouchPhase.Stationary:

                    break;
                case UnityEngine.TouchPhase.Ended:

                    break;
                case UnityEngine.TouchPhase.Canceled:

                    break;
            }
        }

        //判断单点触摸
        if (Input.touchCount == 2)
        {
            //触摸对象1
            Touch touch0 = Input.touches[0];
            //触摸对象1
            Touch touch1 = Input.touches[1];
        }
    }
}

5.4 物体向量移动,添加物体控制组件

a21b866612564aa0b962db8a08c07144.png

编写向量移动脚本

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

public class PlarerControll : MonoBehaviour
{
    public CharacterController characterController;
    // Start is called before the first frame update
    void Start()
    {
        characterController = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update()
    {
        //水平轴
        float horizontal = Input.GetAxis("Horizontal");
        //垂直轴
        float vertical = Input.GetAxis("Vertical");
        //创建成一个方向向量
        Vector2 dir = new Vector2(horizontal,vertical);
        Debug.DrawRay(transform.position, dir, Color.red);
        characterController.SimpleMove(dir);
    }
}

六 鼠标控制物体移动

6.1 2D用transform属性控制移动

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

public class PlarerControll : MonoBehaviour
{
    public CharacterController characterController;
    // Start is called before the first frame update
    void Start()
    {
        characterController = GetComponent<CharacterController>();
    }


    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
           
            //目前的鼠标二维坐标转为三维坐标
            Vector2 curMousePos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
            //目前的鼠标三维坐标转为世界坐标
            curMousePos = Camera.main.ScreenToWorldPoint(curMousePos);
       
           transform.position = curMousePos ;

        }
    }
}

6.2 在携程里面控制物体移动

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

public class PlarerControll : MonoBehaviour
{

    // Start is called before the first frame update
    void Start()
    {
       
      StartCoroutine(OnMouseDown());//在Start方法中调用StartCoroutine(要调用的协程方法)
    }

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

    //协程
    IEnumerator OnMouseDown()
    {
        //1. 得到物体的屏幕坐标
        Vector3 cubeScreenPos = Camera.main.WorldToScreenPoint(transform.position);

        //2. 计算偏移量
        //鼠标的三维坐标
        Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, cubeScreenPos.z);
        //鼠标三维坐标转为世界坐标
        mousePos = Camera.main.ScreenToWorldPoint(mousePos);
        Vector3 offset = transform.position - mousePos;

        //3. 物体随着鼠标移动
        while (Input.GetMouseButton(0))
        {
            //目前的鼠标二维坐标转为三维坐标
            Vector3 curMousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, cubeScreenPos.z);
            //目前的鼠标三维坐标转为世界坐标
            curMousePos = Camera.main.ScreenToWorldPoint(curMousePos);

            //物体世界位置
            transform.position = curMousePos + offset;
            yield return new WaitForFixedUpdate(); //这个很重要,循环执行
        }
    }
}

6.3 用Translate滑动鼠标移动

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

public class PlarerControll : MonoBehaviour
{
   
    // Start is called before the first frame update
    void Start()
    {
     
    }

    // 定义了一个名为sizespeed的公共(public)浮点型(float)变量,初始值为1
    public float sizespeed = 1;
    // 定义了一个名为mouseSpeed的公共浮点型变量,初始值为10
    public float mouseSpeed = 10;  

    // 定义了一个名为lastMousePosition的私有(private)Vector3类型变量
    private Vector3 lastMousePosition;    

    // Update is called once per frame
    void Update()
    {
        // 获取鼠标滚轮的输入值,并将其赋值给名为mouse的局部(local)浮点型变量
        float mouse = -Input.GetAxis("Mouse ScrollWheel");   

        // 鼠标中键按住拖动
        if (Input.GetMouseButton(0))
        {   
            // 获取当前鼠标位置和上一次鼠标位置之间的差值,并将其赋值给名为deltaMousePosition的局部Vector3类型变量
            Vector3 deltaMousePosition = Input.mousePosition - lastMousePosition;
            // 将摄像机的位置向左右和上下移动,移动的距离由鼠标的移动距离和鼠标速度决定
            transform.Translate(deltaMousePosition.x * mouseSpeed * Time.deltaTime, deltaMousePosition.y * mouseSpeed * Time.deltaTime, 0);    

        }
        // 将摄像机的位置向上或向下移动,移动的距离由鼠标滚轮的输入值和大小速度决定
        transform.Translate(new Vector3(0, mouse * sizespeed, 0) * Time.deltaTime, Space.World);
        // 将鼠标当前位置赋值给lastMousePosition变量,以便下一帧计算鼠标位置差值
        lastMousePosition = Input.mousePosition;    

    }
}

七 向量的认识

7.1 向量在游戏角色世界是非常重要的一个概念,上面大部分物体的移动都是通过向量Vector3 

7.2 向量指一个同时具有大小和方向的量. 它通常画为一个带箭头的线段(如下图).线段的长度可以表示向量的大小,而向量的方向也就是箭头所指的方向.物理学中的位移、速度、力等都是矢量

7.3 只要向量的大小和方向相同, 即视为相等的向量, 如下图所示都是相同的向量.

7.4 向量的加法可以用几种三种法则来解释, 比如下面的三角形法则

7.5 向量的减法也有类似运算法则, 三角形法则和平行四边形, 记得箭头总是由减数指向被减数:

7.6 向量 b 与一个标量(实数)相乘还是一个向量, 观察下面的当标量改变时候, 向量 a 的变化:

八 示例,碰撞物体

8.1 创建一个角色

8.2 给角色添加刚体和碰撞体,把重力设为0,不然会向下移动出场景

8.3 新建红色障碍物碰撞体,同时也添加碰撞体

 8.3  在脚本里面编写键盘按键控制物体移动

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

public class MyPlayer : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    public float speed = 5f;//移动速度
    void Update()
    {
        float moveX = Input.GetAxisRaw("Horizontal");//控制水平移动方向 A:-1 D:1 0
        float moveY = Input.GetAxisRaw("Vertical");//控制垂直移动方向 W: 1 S:-1 0
        Vector2 position = transform.position;
        position.x += moveX * speed * Time.deltaTime;
        position.y += moveY * speed * Time.deltaTime;
        transform.position = position;
    }
}

8.5 运行可以看到碰撞到障碍物停止的效果

8.6 优化,发现角色碰到物体会抖动和旋转,旋转需要勾选上脚色刚体的旋转约束属性

8.7 抖动问题需要编写脚本,用刚体的移动替换脚色的移动,修改如下:

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

public class MyPlayer : MonoBehaviour
{

    public Rigidbody2D rbody;

    // Start is called before the first frame update
    void Start()
    {
        rbody = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    public float speed = 10f;//移动速度
  
    void Update()
    {
        float moveX = Input.GetAxisRaw("Horizontal");//控制水平移动方向 A:-1 D:1 0
        float moveY = Input.GetAxisRaw("Vertical");//控制垂直移动方向 W: 1 S:-1 0
        Vector2 position = rbody.position;
        position.x += moveX * speed * Time.deltaTime;
        position.y += moveY * speed * Time.deltaTime;
        //transform.position = position;
        rbody.MovePosition( position);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/997451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tcp连接+套接字编程

tcp头部 tcp端口号 TCP的连接是需要四个要素确定唯一一个连接&#xff1a;&#xff08;源IP&#xff0c;源端口号&#xff09; &#xff08;目地IP&#xff0c;目的端口号&#xff09; 所以TCP首部预留了两个16位作为端口号的存储&#xff0c;而IP地址由上一层IP协议负责传递 源…

autoware.ai感知随笔--地面滤波

autwoware.ai中点云预处理–points_preprocessor points_preprocessor cloud_transformer: 点云坐标转换,将输入的点云转化为velodyne坐标系下的点云。 compare_map_filter: 对比激光雷达点云和点云地图&#xff0c;然后提取&#xff08;或去除&#xff09;一致的点。 |input_…

联通面试题

一、GC 1.1、目标 GC的主要作用是自动识别和释放不再使用的对象&#xff0c;回收其所占用的内存&#xff0c;以防止内存泄漏和内存溢出的问题。 1.2、如何实现 1.2.1、标记阶段 GC从根对象&#xff08;如线程栈中的引用、静态变量等&#xff09;开始&#xff0c;通过可达性…

CnosDB 签约京清能源,助力分布式光伏发电解决监测系统难题。

近日&#xff0c;京清能源采购CnosDB&#xff0c;升级其“太阳能光伏电站一体化监控平台”。该平台可以实现电站设备统一运行监控&#xff0c;数据集中管理&#xff0c;为操作人员、维护人员、管理人员提供全面、便捷、差异化的数据和服务。 京清能源集团有限公司&#xff08;…

【LeetCode】35.复杂链表的复制

题目 请实现 copyRandomList 函数&#xff0c;复制一个复杂链表。在复杂链表中&#xff0c;每个节点除了有一个 next 指针指向下一个节点&#xff0c;还有一个 random 指针指向链表中的任意节点或者 null。 示例 1&#xff1a; 输入&#xff1a;head [[7,null],[13,0],[11,4]…

并发-Executor框架笔记

Executor框架 jdk5开始&#xff0c;把工作单元与执行机制分离开来&#xff0c;工作单元包括Runable和Callable&#xff0c;执行机制由Executor框架来提供。 Executor框架简介 Executor框架的两级调度模型 Java线程被一对一映射为本地操作系统线程 java线程启动会创建一个本…

Linux单列模式实现线程池

目录 一、单列模式 1.1 单列模式概念以及实现条件 1.2 饿汉模式 1.1.1 饿汉模式代码实现 1.1.2 饿汉模式特征和优缺点 1.3 懒汉模式 1.3.1 懒汉模式代码实现 1.3.2 懒汉模式特征以及优缺点 二、线程池 2.1 线程池概念 2.2 实现简单线程池逻辑 2.3 模拟实现懒汉模式线程…

【八大经典排序算法】:直接插入排序、希尔排序实现 ---> 性能大比拼!!!

【八大经典排序算法】&#xff1a;直接插入排序、希尔排序实现 ---> 性能大比拼&#xff01;&#xff01;&#xff01; 一、 直接插入排序1.1 插入排序原理1.2 代码实现1.3 直接插入排序特点总结 二、希尔排序 ( 缩小增量排序 )2.1 希尔排序原理2.2 代码实现2.3 希尔排序特点…

UE5、CesiumForUnreal实现瓦片坐标信息图层效果

文章目录 1.实现目标2.实现过程2.1 原理简介2.2 cesium-native改造2.3 CesiumForUnreal改造2.4 运行测试3.参考资料1.实现目标 参考CesiumJs的TileCoordinatesImageryProvider,在CesiumForUnreal中也实现瓦片坐标信息图层的效果,便于后面在调试地形和影像瓦片的加载调度等过…

【C++入门到精通】C++入门 ——搜索二叉树(二叉树进阶)

阅读导航 前言一、搜索二叉树简介1. 概念2. 基本操作⭕搜索操作&#x1f36a;搜索操作基本代码&#xff08;非递归&#xff09; ⭕插入操作&#x1f36a;插入操作基本代码&#xff08;非递归&#xff09; ⭕删除操作&#x1f36a;删除操作基本代码&#xff08;非递归&#xff0…

给老婆写的,每日自动推送暖心消息

文章の目录 一、起因二、环境准备三、创建nestjs项目四、控制器五、service服务层1、获取Access token2、组装模板消息数据3、获取下次发工资还有多少天4、获取距离下次结婚纪念日还有多少天5、获取距离下次生日还有多少天6、获取时间日期7、获取是第几个结婚纪念日8、获取相恋…

前端面试题JS篇(4)

浏览器缓存 浏览器缓存分为强缓存和协商缓存&#xff0c;当客户端请求某个资源时&#xff0c;获取缓存的流程如下&#xff1a; 先根据这个资源的一些 http header 判断它是否命中强缓存&#xff0c;如果命中&#xff0c;则直接从本地获取缓存资源&#xff0c;不会发请求到服务…

vivado xpm 使用和封装

vivado xpm 使用和封装 tools -> language templates

【JavaScript】WebAPI入门到实战

文章目录 一、WebAPI背景知识1. 什么是WebAPI&#xff1f;2. 什么是API&#xff1f; 二、DOM基本概念三、获取元素三、事件初识1. 点击事件2. 键盘事件 四、操作元素1. 获取/修改元素内容2. 获取/修改元素属性3. 获取/修改表单元素属性4. 获取/修改样式属性 五、操作节点1. 新增…

scratch还原轨迹 2023年5月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析

目录 scratch还原轨迹 一、题目要求 1、准备工作 2、功能实现 二、案例分析

Python:安装Flask web框架hello world

安装easy_install pip install distribute 安装pip easy_install pip 安装 virtualenv pip install virtualenv 激活Flask pip install Flask 创建web页面demo.py from flask import Flask app Flask(__name__)app.route(/) def hello_world():return Hello World! 2023if _…

基于springboot实现的rabbitmq消息确认

概述 RabbitMQ的消息确认有两种。 一种是消息发送确认。这种是用来确认生产者将消息发送给交换器&#xff0c;交换器传递给队列的过程中&#xff0c;消息是否成功投递。发送确认分为两步&#xff0c;一是确认是否到达交换器&#xff0c;二是确认是否到达队列。 第二种是消费接…

【APUE】标准I/O库

目录 1、简介 2、FILE对象 3、打开和关闭文件 3.1 fopen 3.2 fclose 4、输入输出流 4.1 fgetc 4.2 fputc 4.3 fgets 4.4 fputs 4.5 fread 4.6 fwrite 4.7 printf 族函数 4.8 scanf 族函数 5、文件指针操作 5.1 fseek 5.2 ftell 5.3 rewind 6、缓冲相关 6.…

安装samba服务器

1.实验目的 &#xff08;1&#xff09;了解SMB和NETBIOS的基本原理 &#xff08;2&#xff09;掌握Windows和Linux之间&#xff0c;Linux系统之间文件共享的基本方法。 2.实验内容 &#xff08;1&#xff09;安装samba服务器。 &#xff08;2&#xff09;配置samba服务器的…

Visual Studio 线性表的链式存储节点输出引发异常:读取访问权限冲突

问题&#xff1a; 写了一个线性表的链式存储想要输出&#xff0c;能够输出&#xff0c;但是会报错&#xff1a;读取访问权限冲突 分析&#xff1a; 当我们输出到最后倒数第二个节点时&#xff0c;p指向倒数第二个节点并输出&#xff1b; 下一轮循环&#xff1a;p指向倒数第二…