Unity3D赛车游戏+脚本基础

news2024/11/25 19:20:10

前言

游戏对象实例化

Scenes游戏场景

GameObject游戏对象

Component组件

Component使用方法

预制体

Unity事件函数

Instantiate():实例化对象

什么是Time.deltaTime

Transform的移动,旋转和缩放 

实战:赛车游戏

运行演示

具体步骤

游戏打包流程


前言

本章主要介绍Unity的基础开发流程以及涉及到的概念。这个过程需要我们学会编写一些游戏脚本,在这讲的过程中我们会完成一个赛车小游戏,因此,在讲述这些基本概念和流程的时候,会同时涉及到一点脚本的开发基础.

游戏对象实例化

Scenes游戏场景

  • 游戏场景里存储着游戏的环境(诸如游戏模型,地形,UI等),如右图,Unity默认新建的Scene必然有一个摄像机(用于提供渲染视角)和一个光源(提供光照)

GameObject游戏对象

  • 游戏中所有的对象都是GameObject,从模型,光照,摄像机,粒子特效,无一例外。
  • 可是单纯的GO并不能做任何事情,所以,我们需要给一个GO添加属性,让它可以"进化"成游戏角色,模型或者特效等等。
  • 这些属性在Unity中,我们称之为Component(组件)
  • GO默认有一个无法移除的Component:Transform(变换),用于定义位置,缩放和旋转角度。
  • 组合不同的Component(组件),你可以让GO进化成想要的物体。
  • 你可以把GO想象成一个容器,你往里面添加不同的佐料(Component),他们共同作用变成了一道菜。
  • Unity内部提供了一些常用的Component.
  • 如果你想要添加自定义的Cmponent,需要自己写脚本实现

Component组件

每一个GO都默认有个Transform组件

  •  Position(位置 在哪里?)
  • Rotation(旋转 朝南还是朝北?)
  • Scale(缩放 大还是小?)

一个Camera(摄像机)默认添加的Component

 每一个可以折叠的都是组件,组件定义了GO的行为和属性

Component使用方法

右键Component可以展开功能菜单如右图:

组件的属性在游戏运行时都可以手动的更改的,效果可以在Game View或者Scence Viem中直接看到。

预制体

  • Prefab是一种资源类型——存储在项目视图中的一种可反复使用的游戏对象。因而当游戏中需要非常多反复使用的对象,资源等时,Prefab就有了用武之地,它拥有下面特点:

1.能够放在多个场景中。也能够在同一个场景中放置多次

2.当加入一个Prefab到场景中,就创建了他的一个实例

3.全部的Prefab实例链接到原始Prefab,本质上是原始Prefab的克隆。

4.不论项目中存在多少个实例。仅仅要对Prefab进行了改动。全部Prefab实例都将随之发生变化

Unity事件函数

  • Unity中的脚本分为不同的方法,不同的方法在特定的情况下被回调会实现特定的功能。

-Awake方法:有一个场景仅仅调用一次,在该方法内可以写一些游戏场景初始化之类的代码。

-Start方法:这个方法在GO被启用时调用

-Update方法:这个方法会在每一帧渲染之前被调用,大部分游戏代码在这里执行,除了物理部分的代码。

-FixeUpdate方法:这个方法会在固定的物理时间步调调用一次。这里也是基本物理行为代码执行的地方。

Instantiate():实例化对象

例子:脚本完成5个预制体

-向量:Unity中提供了完整的用来表示二维向量的Vector2类和表示三维向量的Vector3类

-实例化游戏对象

static function Instantiate(original:Object,position:Vector3,rotation:Quaternion):Object
vector3(2,0,0)
  • 参数一:是预设
  • 参数二:实例化预设的坐标
  • 参数三:实例化预设的旋转角度

什么是Time.deltaTime

  • 在游戏,电影和动画中,都有一个渲染的帧率,电影是24帧/s,游戏大概是30帧/s(当然也有60帧/s的)。在unity里面1秒钟,Update方法执行了30次。
  • 1秒钟有30帧,帧与帧之所消耗的时间是不一样的,那么我如何知道上一帧用了多少时间?Time.deltaTime就是为了解决这个问题。放在update()函数中的代码是以帧来执行的,如果我们需要物体的移动以秒来执行,需要将物体移动的值乘以Time.deltaTime.
  • 物理中距离=速度*时间,通过把Speed*Time.deltaTime,计算得到上一帧游戏物体移动的距离。

Transform的移动,旋转和缩放 

-Translate(Vector3 translation)

-Rotate(Vector3 eulers)

-localScale

实例演示

  • 脚本完成5个预制体

首先创建在"_Scripts"下创建一个脚本,然后写入代码,用for循环创建5个预制体,保证每个预制体的x轴发生变化,其他坐标轴不发生变化,

代码如下所示: 

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

public class createbox : MonoBehaviour
{
    public GameObject go;
    // Start is called before the first frame update
    void Start()
    {
        for(int i=0;i<5;i++)
        {
            Vector3 pos = new Vector3(i * 2,0, 0);
            GameObject.Instantiate(go, pos, Quaternion.identity);
        }
      
        
    }

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

然后将代码拖入到Camera中,然后点击Camera查看右边的组件,找到代码中创建的go.

 将预制体拖入GO中即可。

运行结果:

  • 让一个Cube沿着矩形移动中间Cube沿着x轴方向旋转,并扩大到4倍,然后缩小至0.5倍

运行结果

代码示例:将对应的脚本拖入到对应的物体中。

 代码如下:

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

public class rotating : MonoBehaviour
{
    public float speed = 0.1f;
    public bool flag = true;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.Rotate(Vector3.right*speed*Time.deltaTime);
        if(transform.localScale.x<0.5)
        {
            flag = true;
           // transform.localScale += new Vector3(0.1f, 0.1f, 0.1f);
        }
        if(transform.localScale.x>5)
        {
            flag = false;
        }
        if(flag)
        {
            transform.localScale += new Vector3(0.1f, 0.1f, 0.1f);
        }
        else
        {
            transform.localScale -= new Vector3(0.1f, 0.1f, 0.1f);
        }
    }
}
//moving.cs

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

public class moving : MonoBehaviour
{
    public float speed = 5.0f;
   
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //transform.Translate(Vector3.forward * speed*Time.deltaTime);
        if(transform.position.z>6)
        {
            transform.Translate(new Vector3(-speed * Time.deltaTime, 0, 0));
        }
        if(transform.position.x<-6)
        {
            transform.Translate(new Vector3(0, 0, -speed * Time.deltaTime));
        }
        if(transform.position.z<-6)
        {
            transform.Translate(new Vector3(speed * Time.deltaTime, 0, 0));
        }
        if(transform.position.x>6)
        {
            transform.Translate(new Vector3(0, 0, speed * Time.deltaTime));
        }
    }
}

//createbox.cs

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

public class createbox : MonoBehaviour
{
    public GameObject go;
    // Start is called before the first frame update
    void Start()
    {
        for(int i=0;i<5;i++)
        {
            Vector3 pos = new Vector3(i * 2,0, 0);
            GameObject.Instantiate(go, pos, Quaternion.identity);
        }
      
        
    }

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

注意:

  • Awake在物体初始化就会被调用,不管脚本本身是否启用;
  • Start方法只有在被激活的状态下才会被调用;
  • Quaternion.indetity就是指Quaternion(0,0,0,0),就是每旋转前的初始角度,是一个确切的值。

实战:赛车游戏

运行演示

具体步骤

1.导入资源包,我把实验需要用到的资源包放在下面,需要的自取

资源包

2.首先在scene中找到"警车",把它拖动到文件夹_Prefabs,生成一个新的prefab,并重新命名为player,把player拖动到场景中,放置在路的开头,调整下camera的位置,让它正对着警车的尾部,然后让警车能够跑起来,我们创建一个"PlayerMoving.cs"脚本;

运行结果:

 代码:

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

public class PlayerMoving : MonoBehaviour
{
    public float moveSpeed = 5.0f;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.position += new Vector3(0, 0, moveSpeed*Time.deltaTime);
    }
}

问题:我们会发现车越走越远,不符合游戏的体验,所以我们要让镜头跟随着车子移动

3.需要记录camera一开始离警车有多远,因为3D游戏分布需要记录(X,Y,Z)的偏移

 为了让我们的摄像机也能动起来,我们创建一个"CameraMove.cs"脚本,因为UNITY里面,不同脚本的update执行顺序是无序的,为了保证先移动小车再移动camera,所以要在LateUpdate里面。

  代码如下:

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

public class CameraMoving : MonoBehaviour
{
    public GameObject player;
    public Vector3 distance;
    // Start is called before the first frame update
    void Start()
    {
        distance = transform.position - player.transform.position;
    }

    // Update is called once per frame
    void LateUpdate()
    {
        transform.position = distance + player.transform.position;
    }
    
}

4.为了让我们能够用键盘控制警车(左右移动和加速减速),我们创建一个"PlayerControl.cs"脚本;

 代码如下:

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

public class PlayerControl : MonoBehaviour
{
    public float HorSpeed = 5.0f;
    public float verSpeed = 5.0f;
    public float maxSpeed = 20.0f;
    public PlayerMoving player;
    // Start is called before the first frame update
    void Start()
    {
        player = transform.GetComponent<PlayerMoving>();
    }

    // Update is called once per frame
    void Update()
    {
        float horDeltal = Input.GetAxis("Horizontal");
        Debug.Log(horDeltal);
        if(horDeltal!=0)
        {
            transform.position += new Vector3(horDeltal * HorSpeed * Time.deltaTime, 0, 0);
        }
        float verDeltal = Input.GetAxis("Vertical");
        if(verDeltal!=0)
        {
            player.moveSpeed += verDeltal * verSpeed * Time.deltaTime;
            if(Mathf.Abs(player.moveSpeed)> maxSpeed)
            {
                player.moveSpeed = verDeltal * maxSpeed;
            }
           // transform.position += new Vector3(0,0,verDeltal*verSpeed*Time.deltaTime);
        }
    }
}

 5.加入粒子Prefab,现在我们的小车虽然有了加速的功能,却没有加速效果。在Unity中,效果都使用粒子引擎实现的。让我们先不要管粒子的制作细节,加入我们已经制作好了两个粒子Prefab,怎么把他们加入到游戏中?在player中新建两个空的GameObject,分别命名为:effectPosition1,effectPostion2.把他们移动到你想要产生粒子效果的位置,在我们这个例子中,也就是骑车排气管的位置。然后编写脚本,设置两个public  Transform类型的变量,这样我们就可以在脚本中知道粒子产生的位置。

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

public class PlayerControl : MonoBehaviour
{
    public float HorSpeed = 5.0f;
    public float verSpeed = 5.0f;
    public float maxSpeed = 20.0f;
    public PlayerMoving player;
    public GameObject effexp;
    public Transform effPos1;
    public Transform effPos2;
    // Start is called before the first frame update
    void Start()
    {
        player = transform.GetComponent<PlayerMoving>();
    }

    // Update is called once per frame
    void Update()
    {
        float horDeltal = Input.GetAxis("Horizontal");
        Debug.Log(horDeltal);
        if(horDeltal!=0)
        {
            transform.position += new Vector3(horDeltal * HorSpeed * Time.deltaTime, 0, 0);
        }
        float verDeltal = Input.GetAxis("Vertical");
        if(verDeltal!=0)
        {
            player.moveSpeed += verDeltal * verSpeed * Time.deltaTime;
            if(Mathf.Abs(player.moveSpeed)> maxSpeed)
            {
                player.moveSpeed = verDeltal * maxSpeed;
            }
           // transform.position += new Vector3(0,0,verDeltal*verSpeed*Time.deltaTime);
        }
        if(Input.GetKeyDown(KeyCode.W)||Input.GetKeyDown(KeyCode.UpArrow))
        {
            GameObject.Instantiate(effexp, effPos1.position, Quaternion.identity);
            GameObject.Instantiate(effexp, effPos2.position, Quaternion.identity);
        }
    }
}

销毁游戏对象:把脚本挂在粒子效果预制体上,实现3秒钟自动销毁

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

public class effDestroy : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        GameObject.Destroy(this.gameObject, 3.0f);
    }

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

大家可以下去思考独自完成转弯和碰撞的功能。 

游戏打包流程

1.选择File->Build Setting

2.添加场景Scene

3.Player Settings设置图标,欢迎界面等

4.Build Setting 

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

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

相关文章

智慧教育解决方案-最新全套文件

智慧教育解决方案-最新全套文件一、建设背景二、思路架构三、建设方案四、获取 - 智慧教育全套最新解决方案合集一、建设背景 目前数字化校园现状&#xff1a; 各自为政 分散建设 各个学校组成的业务系统、网站五花八门&#xff0c;形式多样。形式单一 功能简单 学校网站主要…

为什么同一表情‘‘.length==5但‘‘.length==4?本文带你深入理解 String Unicode UTF8 UTF16

背景 为什么同样是男人&#xff0c;但有的男人&#x1f9d4;‍♂️.length 5&#xff0c;有的男人&#x1f9d4;‍♂.length 4呢&#xff1f; 这二者都是JS中的字符串&#xff0c;要理解本质原因&#xff0c;你需要明白JS中字符串的本质&#xff0c;你需要理解 String Unic…

vlan trunk stp攻防

目录 一、VLAN、Trunk面临的安全风险 trunk干道攻击DTP攻击&#xff08;思科特有&#xff09; VLAN跳跃攻击 STP根桥攻击 二、攻击防护 一、VLAN、Trunk面临的安全风险 trunk干道攻击DTP攻击&#xff08;思科特有&#xff09; 在华为设备中trunk链路是手工指定的&#xf…

A-LEVEL Chemistry考点分析

A-LEVEL化学其实不是一门很难的科目&#xff0c;并没有太多的内容&#xff0c;虽说包含十几章的内容但其实每章都是相互关联&#xff0c;一通百通&#xff0c;掌握元素周期表的实质&#xff0c;基本上就没有什么问题了&#xff0c;重在理解&#xff01;知识点多而不碎&#xff…

如何一站式管理固定资产的全生命周期?

目前很多企业还在沿用之前传统的Excel表格来管理和盘点固定资产&#xff0c;不但加大了企业固定资产管理员的工作量&#xff0c;而且在实际的操作过程中容易出现错登记、漏盘点、无法查询操作履历等各种小插曲。而且随着企业固定资产数量、种类、分支机构以及人员的不断增加&am…

juc之常用4大并发工具类 (四)

CountDownLatch: 减少计数CyclicBarrier: 循环栅栏Semaphore: 信号量ExChanger: 交换器 文章目录1.CountDownLatch2.CyclicBarrier3.Semaphore4.Exchanger1.CountDownLatch CountDownLatch,俗称闭锁,作用是类似加强版的 Join,是让一组线程等待其他的线程完成工作以后才执行 就…

数仓开发之DWD层(四)

目录 十一&#xff1a;工具域优惠券领取事务事实表 11.1 主要任务&#xff1a; 11.2 思路分析&#xff1a; 11.3 图解&#xff1a; 十二&#xff1a;工具域优惠券使用&#xff08;下单&#xff09;事务事实表 12.1 主要任务&#xff1a; 12.2 思路分析&#xff1a; 12.3…

[附源码]Python计算机毕业设计 社区老人健康服务跟踪系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Java项目实战【超级详细】

软件开发流程 角色分工 开发环境搭建 创建普通Maven项目编写pom.xml导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instanc…

【MQ简单模式】

14天阅读挑战赛 MQ简单模式 1、模式介绍 需求&#xff1a;使用简单模式完成消息传递 步骤&#xff1a; ① 创建工程&#xff08;生成者、消费者&#xff09; ② 分别添加依赖 ③ 编写生产者发送消息 ④ 编写消费者接收消息 在上图的模型中&#xff0c;有以下概念&#xff1a; ⚫…

数据库索引的基本操作(sql语句)

表索引的增删改查&#xff08;sql语句&#xff09; 概念&#xff1a; 索引由表中的一列或多列组合而成&#xff0c;目的是优化数据库的查询速度。向索引表中插入数据时&#xff0c;数据库系统需要按照索引进行排序。有时&#xff0c;可以先将索引删除&#xff0c;然后向表插入…

Docker学习(1)—— 安装Docker

一. 安装Docker 1. 查看CentOS是否是7以上的版本 cat /etc/redhat-release 2. 安装gcc yum -y install gcc yum -y install gcc-c 3. 安装需要的软件包 yum install -y yum-utils 4. 设置stable镜像仓库 yum-config-manager --add-repo http://mirrors.aliyun.com/doc…

p38 MAPK调控酶及转录因子

MAPK 与 p38 MAPK 作为对外界物理和化学性质变化的响应&#xff0c;哺乳动物细胞激活有丝分裂原激活蛋白激酶 (MAPK) 的四个特征性亚家族&#xff1a;ERK1/2、JNK、p38 和 ERK5。其中 p38 MAPKs 是一类保守的丝氨酸-苏氨酸蛋白激酶&#xff0c;可被多种细胞外炎症因子 (如TNF-α…

语义分割及DeeplabV3+模型

一、基本概念 将视觉输入分为不同的语义可解释类别&#xff1b;通俗点说就是区分不同部分。 分类&#xff1a; b)语义分割 c)实例分割 d)全景分割 语义分割一般以平均IOU(Intersection Over Union,并交比)来评价性能&#xff0c;其公式如下&#xff1a; 目的是使…

Python学习----Demo(pyecharts)

PyEcharts 就是百度的Echarts&#xff0c;针对Python有一款专门的&#xff0c;所以就叫PyEcharts 官方网站&#xff1a; 文档&#xff1a; https://pyecharts.org/#/zh-cn/ 示例&#xff1a; https://gallery.pyecharts.org/#/README 通过pip安装 pip install pyecharts 或者…

关于Docker中容器之间互相访问问题

背景&#xff1a; 在学习 Docker 过程中&#xff0c;自己先开启了一个 mysql 容器&#xff0c;并且通过端口映射Navicat可以远程连接 后来在部署 nacos 过程中&#xff0c;对于其中参数 MYSQL_SERVICE_HOST 配置 mysql 的 IP 时 首先配置的是 localhost&#xff0c;结果 nacos…

Opencv项目实战:16 虚拟拖拽系统

0、项目介绍 这次使用cvzone模块&#xff0c;制作一个虚拟拖拽系统&#xff0c;我们根据索引可以知道食指与中指的索引为8和12&#xff0c;当两指间合并时可以对虚拟方块进行拖拽&#xff0c;张开时解除拖拽&#xff0c;方块停在此处。虽然目前仍然存在一定的bug&#xff0c;即…

网站seo怎么优化?

一、网站搭建 1、选择合适的建站软件。 2、网站模板的选择。 3、title的选择至关重要。 4、长尾关键词的选择。 二、站内优化 1、首页title keywords description等布局好要优化的关键词&#xff0c;页面中间和底部也要布局关键词且用标签加粗&#xff01; 2、网站 URL静态。…

Go runtime剖析系列(一):内存管理

Go 的内存管理总览 程序在运行过程中会不断的调用分配器分配堆内存&#xff0c;同时也会通过赋值器更新内存数据&#xff0c;如果我们将内存看做为一个个小的对象集合&#xff0c;那程序的运行其实就是更改这个对象图&#xff0c;其中分配器在这个对象图中创建节点&#xff0c…

Flutter 的缓存策略

Flutter 的缓存策略 原文 https://medium.com/romaingreaume/implementing-a-cache-strategy-in-your-flutter-app-5db3e316e7c9 前言 在移动应用程序中&#xff0c;缓存管理是一件非常重要的事情。 在本文中&#xff0c;我将告诉您如何在我的公司 Beapp 中设置策略缓存。 正文…