五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑。本系列文章以C#为介绍语言,基于Unity2017.4.x。

一、环境搭建

我使用的是Unity+VSCode,用的是mac系统,windows的自己搜资料,步骤差不多。

1.安装Unity:下载Unity,我下载的是Unity2017.4.21f1。下载下来是一个下载助手UnityDownloadAssistant-2017.4.21f1.dmg,双击打开安装。选择安装内容Unity2017.4.21f1、MonoDevelop/Unity Debugger、Documentation、Standard Assets。

2.安装VSCode:个人喜好,VSCode比较轻量,写代码流畅一点。下载最新版本就可以。

3.下载dotnet:我下载的是dotnet-dev-osx-x64.1.1.11.pkg,双击打开安装。

4.安装VSCode插件:插件可以选择unity3d-pack,由于我安装失败,所以把unity3d-pack里面的插件都安装了一遍:

C#

C# FixFormat

C# Snippets

  C# XML Documentation Comments

Debugger for Unity

eppz! (C# theme for Unity)

MonoBehaviour Snippets

ShaderlabVSCode(Free)

Unity Code Snippets

Unity Tools

5.建立Unity项目:打开Unity,我新建的是2D项目

6.建立C#项目,目的是让VSCode对C#代码有提示。终端命令行cd到Unity项目根目录,运行命令dotnet new console创建dotnet命令行工程。Unity项目根目录下会生成 xx.csproj文件、obj目录、bin目录

7.添加unity库引用,目的是让VSCode能识别Unity的命名空间(UnityEngine、UnityEngine.UI等)。打开obj/project.assets.json文件,在compile节添加unity库路径,包括(有用到其他库自己添加):

"/Applications/Unity/Unity.app/Contents/Managed/UnityEngine.dll": {},

"/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll": {},

这样,Unity+VSCode的环境就搭建好,可以用VSCode写脚本了。

二、编辑器简介

1.工程结构管理器

2.场景层级管理器

3.场景编辑器

4.属性编辑器

新建工程时,工程结构管理器中,Assets目录下为空,可以在下面创建场景,双击场景在场景层级管理器看到它的结构,在场景编辑器里可视化编辑,右边的属性编辑器可以对相应对GameObject设置属性、添加组件(包括脚本)。有使用过cocos creator经验会很熟悉,不详述。

三、熟悉开发流程

首先必须了解一些基本概念,

1.在Unity里,游戏由GameObject组成(可以理解成cocos里的cc.Node),GameObject可以添加组件

2.组件基类为Component,但用户自定义的脚本都继承自MonoBehaviour(Component的子类,如同cocos creator里的cc.Component)

3.每个GameObject有基本的Transform,设置GameObject的坐标

Assets目录是游戏开发所有资源存放的地方,包括图片、声音、脚本资源。我开发游戏,一般只做一个scene,Assets目录下新建一个目录Scene,在下面新建场景Main(在文件系统中可以看到它的全称是Main.unity)。

双击,在场景层级管理器中可以看到它的层级结构,默认只有一个Main Camera。为了支持屏幕适配,编写一个C#脚本,在Assets目录下新建一个目录Script,用于存放C#脚本。新建C#脚本MainCamera(文件系统中MainCamera.cs),用VSCode打开(VSCode直接打开整个项目的根目录),添加以下代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class MainCamera : MonoBehaviour { public float designWidth = 6.4f;
public float designHeight = 9.6f; // Use this for initialization
void Start () {
float screenHeight = Screen.height;
float orthographicSize = this.GetComponent<Camera>().orthographicSize;
float aspectRatio = Screen.width * 1.0f / Screen.height;
// fix the litte side
if (aspectRatio < designWidth / designHeight) { // fix width
orthographicSize = designWidth / (2 * aspectRatio);
this.GetComponent<Camera>().orthographicSize = orthographicSize;
Debug.Log("FIX_WIDTH, orthographicSize is " + orthographicSize);
} else { // fix height
orthographicSize = designHeight / 2;
this.GetComponent<Camera>().orthographicSize = orthographicSize;
Debug.Log("FIX_HEIGHT, orthographicSize is " + orthographicSize);
}
} // Update is called once per frame
void Update () { }
}

  

在Unity编辑器的场景层级管理器选择Main Camera,在属性编辑器中给它添加组件(Add Component -> Scripts -> Main Camera),现在可以设置游戏的设计分辨率了。

游戏启动后,会根据GameObject“Main Camera”的生命周期触发Main Camera脚本的Start方法,根据游戏尺寸对照相机调整显示高度(不适用于UGUI,UGUI待会介绍)。该适配方案要注意几个概念,Unity默认单元大小为100个像素,所以宽高是实际像素数除以100,照相机的orthographicSize等于照相机显示高度的一半。如设置为6.4x9.6,那么美术出资源时一屏的大小就是640x960。不同的手机屏幕自动做等比例缩放,具体缩放倍数,当实际屏幕宽高比小于设计分辨率时宽缩放到跟实际屏幕一样,否则高缩放到跟实际屏幕一样。另外一边相应等比例缩放,小的一边铺满全屏可以避免出现黑边,但也导致被裁剪,这种方式主要针对全屏的场景。

给主场景添加两个GameObject:SceneLayer和PopupLayer,分别作为场景和弹窗的根节点。

默认组件Transform只有位置没有大小,换成组件RectTransform,设置其大小为设计分辨率

 
现在可以写游戏入口代码了,在Script目录新建脚本StartCtrl.ts,添加两个属性sceneLayer、popupLayer用于跟编辑器场景中的两个GameObject关联。
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class StartCtrl : MonoBehaviour { public GameObject sceneLayer = null;
public GameObject popupLayer = null; // Use this for initialization
void Start () { } // Update is called once per frame
void Update () { }
}

  

在Unity编辑器的场景层级管理器选择Main Camera,在属性编辑器中给它添加组件(Add Component -> Scripts -> Start Ctrl),把场景层级管理器的sceneLayer、popupLayer拖到对应的属性完成关联。启动游戏后,GameObject“Main Camera”的生命周期就会触发StartCtrl里对应的方法,StartCtrl里的sceneLayer和popupLayer属性已被赋值为Main场景对应的子节点。后面我们会继续讲解如何使用这两个属性对界面进行分层管理。

我们先看看怎样制作界面。我们可以把每一个界面都做成一个prefab预制体。Assets目录下新建一个目录Resources(该目录资源可以用Resources.Load直接加载),Resources目录下新建一个目录Prefabs,预制体放到这个目录(Unity建议使用AssetBoundle方式,可以将资源分包,后面调整结构)。
 
制作预制体的方法很简单。先双击Scene/Main.unity打开,新建空GameObject,属性面板将新GameObject名字改为TestView,修改Transform组件为RectTransform组件,设置大小为设计分辨率,如6.4x9.6(注意1个单元100个像素),拖动该GameObject到工程结构管理器面板的Assets/Resources/Prefabs目录。这样一个预制体TestView就生成了。
 
预制体编辑完后可以从场景中删除,需要再次编辑时从Prefabs目录拖回场景中,修改完后点击属性面板的Apply同步,并从场景中删除。
 
在预制体里添加UI -> Text,会自动添加Canvas和EventSystem,一个负责渲染一个负责事件处理。这里需要对界面做适配,Canvas属于UGUI,需要在Canvas Scaler组件设置其设计分辨率和适配方案,其中这里填的大小是设计分辨率的一半,如640x960填320x480。Match 0表示宽缩放到跟实际屏幕一样,1表示高缩放到跟实际屏幕一样。另外一边相应等比例缩放。
 
 
同样我们可以开始写这个界面的脚本TestViewCtrl.cs,控制界面逻辑和刷新。这个脚本还是继承MonoBehaviour,定义对应的Text等类型的属性(记得using UnityEngine.UI),这样就可以把界面的元素关联到脚本,通过脚本来刷新。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; public class TestViewCtrl : MonoBehaviour { public Text txtHello = null; // Use this for initialization
void Start () {
txtHello.text = "你好";
} // Update is called once per frame
void Update () { }
}

  

打开回刚才那个预制体,选择根GameObject,在属性面板选择添加组件TestViewCtrl,并将对应ui组件拖到脚本组件的属性上进行关联,这样我们就可以通过TestViewCtrl控制这个界面了。

 
要显示这个界面,首先要加载prefab。Unity提供了Resources.Load方法,加载Resources目录下的资源(不要填后缀名),加载成功后通过Instantiate方法把预制体实例出一个GameObject,Unity的界面布局也是基于组合模式的一棵树,transform通过SetParent把自己添加到父的GameObject。所以,我们通过gameObj.transform.SetParent把这个界面放到屏幕,这些代码可以写在入口脚本StartCtrl的Start方法里。可以通过GameObject.GetComponent获取TestViewCtrl的实例来操作界面。不过,我一般是通过MonoBehaviour的生命周期和消息来实现界面更新,降低耦合,后面会详细介绍这种方式。
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class StartCtrl : MonoBehaviour { public GameObject sceneLayer = null;
public GameObject popupLayer = null; // Use this for initialization
void Start () {
Object prefab = Resources.Load("Prefabs/TestView", typeof(GameObject));
if (!prefab) {
Debug.Log("Prefab is null");
return;
} GameObject gameObj = Instantiate(prefab) as GameObject;
gameObj.transform.SetParent(popupLayer.transform);
} // Update is called once per frame
void Update () { }
}

  

现在我们已经知道怎样建立游戏入口,怎样制作、加载、显示界面,下一章将讲解怎样对弹窗分层管理。

Unity MMORPG游戏开发教程(一)——初识Unity的更多相关文章

  1. Unity 2D游戏开发教程之精灵的死亡和重生

    Unity 2D游戏开发教程之精灵的死亡和重生 精灵的死亡和重生 目前为止,游戏项目里的精灵只有Idle和Walking这两种状态.也就是说,无论精灵在游戏里做什么,它都不会进入其它的状态,如死亡.于 ...

  2. Unity 2D游戏开发教程之摄像头追踪功能

    Unity 2D游戏开发教程之摄像头追踪功能 上一章,我们创建了一个简单的2D游戏.此游戏中的精灵有3个状态:idle.left和right.这看起来确实很酷!但是仅有的3个状态却限制了精灵的能力,以 ...

  3. Unity 2D游戏开发教程之使用脚本实现游戏逻辑

    Unity 2D游戏开发教程之使用脚本实现游戏逻辑 使用脚本实现游戏逻辑 通过上一节的操作,我们不仅创建了精灵的动画,还设置了动画的过渡条件,最终使得精灵得以按照我们的意愿,进入我们所指定的动画状态. ...

  4. Unity 2D游戏开发教程之游戏精灵的开火状态

    Unity 2D游戏开发教程之游戏精灵的开火状态 精灵的开火状态 “开火”就是发射子弹的意思,在战争类型的电影或者电视剧中,主角们就爱这么说!本节打算为精灵添加发射子弹的能力.因为本游戏在后面会引入敌 ...

  5. Unity 2D游戏开发教程之游戏中精灵的跳跃状态

    Unity 2D游戏开发教程之游戏中精灵的跳跃状态 精灵的跳跃状态 为了让游戏中的精灵有更大的活动范围,上一节为游戏场景添加了多个地面,于是精灵可以从高的地面移动到低的地面处,如图2-14所示.但是却 ...

  6. Unity 2D游戏开发教程之为游戏场景添加多个地面

    Unity 2D游戏开发教程之为游戏场景添加多个地面 为游戏场景添加多个地面 显然,只有一个地面的游戏场景太小了,根本不够精灵四处活动的.那么,本节就来介绍一种简单的方法,可以为游戏场景添加多个地面. ...

  7. Unity多玩家网络游戏开发教程1章Unity带有网络功能

    Unity网络多玩家游戏开发教程第1章Unity自带网络功能 Unity拥有大量的第三方插件.专门提供了对网络功能的支持. 可是.大部分开发人员第一次接触到的还是Unity自带的网络功能.也就是大家常 ...

  8. Unity 3D游戏开发学习路线(方法篇)

    Unity 3D本来是由德国的一些苹果粉丝开发的一款游戏引擎,一直只能用于Mac平台,所以一直不被业外人士所知晓.但是后来也推出了2.5版,同时发布了PC版本,并将其发布方向拓展到手持移动设备.Uni ...

  9. Unity 2D游戏开发教程之2D游戏的运行效果

    Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑问 ...

随机推荐

  1. 用PCA(主成分分析法)进行信号滤波

    用PCA(主成分分析法)进行信号滤波 此文章从我之前的C博客上导入,代码什么的可以参考matlab官方帮助文档 现在网上大多是通过PCA对数据进行降维,其实PCA还有一个用处就是可以进行信号滤波.网上 ...

  2. 学会python可以上天!20行代码获取斗鱼平台房间数据,就是这么牛逼!

    Python(发音:英[?pa?θ?n],美[?pa?θɑ:n]),是一种面向对象.直译式电脑编程语言,也是一种功能强大的通用型语言,已经具有近二十年的发展历史,成熟且稳定.它包含了一组完善而且容易理 ...

  3. keras实现简单性别识别(二分类问题)

    keras实现简单性别识别(二分类问题) 第一步:准备好需要的库 tensorflow  1.4.0 h5py 2.7.0 hdf5 1.8.15.1 Keras     2.0.8 opencv-p ...

  4. Redis持久化方式的选择

    本文将介绍Redis持久化的两种方式:快照持久化和AOF持久化,并对两种方法进行分析和对比,方便在实际中做出选择. 持久化 什么是持久化 Redis所有数据保存在内存中,对数据的更新将异步地保存到磁盘 ...

  5. Python练习:九九乘法表

    打印 n * n 的乘法表 #打印 9*9 乘法表 def Multiplication(n): # n - 定义打印的行数 max_len = len(str((n)**2)) #计算最大值的占位( ...

  6. 了解Scala反射

    本篇文章主要让大家理解什么是Scala的反射, 以及反射的分类, 反射的一些术语概念和一些简单的反射例子. 什么是反射 我们知道, Scala是基于JVM的语言, Scala编译器会将Scala代码编 ...

  7. 分析Class类和ClassLoader类下的同名方法getResourceAsStream

    在读取本地资源的时候我们经常需要用到输入流,典型的场景就是使用Druid连接池时读取连接池的配置文件.Java为我们提供了读取资源的方法getResourceAsStream(),该方法有三种: Cl ...

  8. Nginx的“远方表哥”—Tengine

    本文收录在Linux运维企业架构实战系列 今天想起当初研究nginx反向代理负载均衡时,nginx自身的upstream后端配置用着非常不舒服: 当时使用的淘宝基于nginx二次开发的Tengine, ...

  9. TCP的三次握手与四次挥手

    TCP的三次握手与四次挥手 一.TCP(Transmission Control Protocol 传输控制协议) TCP是面向对连接,可靠的进程到进程通信的协议 TCP是提供全双工服务,即数据可在同 ...

  10. The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

    使用EF时,在Limda表达式中( query.Where(x => x.CheckInDate >= bd.Date);)查询的时候抛出了这个异常,网上查到的发现,并不能解决问题. 后来 ...