您现在的位置是:首页 >技术杂谈 >unity的学习,准备搞一款mmo小游戏,服务器和客户端从零学网站首页技术杂谈
unity的学习,准备搞一款mmo小游戏,服务器和客户端从零学
先学一下unity,mmo服务器框架到时候在学习一下,暂时服务器简单做一下
C# 脚本生命周期
如代码所示,简单了解一下。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour
{
void Awake()
{
Debug.Log("awake hello world!");
}
// 当脚本可用时,也就是打勾的时候可以使用
void OnEnable()
{
Debug.Log(" OnEnable");
}
// Start is called before the first frame update
// 这个也是只会初始化一次
void Start()
{
Debug.Log("start");
}
// Update is called once per frame,下面两个函数都和帧相关,一先一后的调用关系
void Update()
{
Debug.Log("update");
}
private void LateUpdate()
{
Debug.Log("LateUpdate");
}
// 这个是定时进行刷新
private void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
private void OnDisable()
{
}
// 销毁,移除脚本就认为是销毁了组件,或者启动关闭了
private void OnDestroy()
{
Debug.Log("OnDestroy");
}
}
编辑脚本的执行顺序
我个人感觉不要一个放在Awake函数中,一个放在Start中。因为这只适合两个脚本使用,如果多个脚本还是没有办法解决脚本执行的顺序。在这里设置脚本的执行顺序,添加进去的值越小在队列中越靠前越先执行
物体标记
给标签换个颜色就能看见文本了。
图层
可以根据不同图层来做碰撞检测,目前还没有做,简单的了解一下
预设体
修改预设体的值,大家都变了,这样省的一个变了,其他的还要手调,但如果只需要这某一个物体变了,就不要改变预设体的值,而是单独操作这个对象。要改变预设体就直接改右边,如果改单独的一个对象,就改左边的值。试了下材质是一改都要改的,只动一个是不可以的。
预设体生成
就是把左侧的组件收拾一下直接拖到右边即可
找不到预设体怎么办?
找不到对应的预设体就点一下这个选择
修改一个预设体物体不操作预设体本体怎么做
点一下打开,这样操作就会直接影响预设体的本体从而影响所有采用预设体的物体了。
预设体变体
相当于多个基类的感觉,图标变的有点灰色。怎么创建的?就是先有了预设体,在改变了一部分东西在拖拽一下发现有变化会自动提示是否需要预设体变体的
欧拉与四元数转换
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 欧拉角,四元数
// unity 用的是四元数
Vector3 v = new Vector3(0, 30, 0);
Quaternion q = Quaternion.identity; // 四元数
// 通过欧拉角创建四元数
q = Quaternion.Euler(v);
// 看向一个物体,我猜打怪的时候,玩家视野自动移入
q = Quaternion.LookRotation(v);
// 四元数转为欧拉
var v2 = q.eulerAngles;
}
// Update is called once per frame
void Update()
{
}
}
调试
我以为是代码进行debug,不是的,是画线来进行调试,我猜这样方便后面好学习视野的范围
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DebugTest_22 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// 绘制一条线
Debug.DrawLine(Vector3.zero, Vector3.one,Color.blue);
// 绘制一条射线
Debug.DrawRay(Vector3.zero, Vector3.up, Color.red);
}
}
获取对象实例
可以简写gameObject获取属性,C#有点厉害,类里可以不用写this指针直接调用类对象。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Empty_23 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 获取对象的这个实例
GameObject go = this.gameObject;
Debug.Log(go.name);
// 简便写法
Debug.Log(gameObject.name);
// tag标签
Debug.Log(gameObject.tag);
// 图层
Debug.Log(gameObject.layer);
}
// Update is called once per frame
void Update()
{
}
}
生成gameObject对象,可以在A物体操作B物体
声音一个对象即可,然后在unity编辑器上给他附一个新值
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Empty_23 : MonoBehaviour
{
public GameObject myFirstNewGameObj;
// Start is called before the first frame update
void Start()
{
Debug.Log(String.Format("myFirstNewGameObj name:{0}",myFirstNewGameObj.name));
}
// Update is called once per frame
void Update()
{
}
}
在unity编辑器这里设置上一个对象就可以正常使用了
对象是对象,组件是组件
我以为可以gameObject走天下,没想到大意了,并不能一个gameObject走天下,只有transform这个组件封了个对象,因为这是必需的,其他组件如果利用模板函数来生成一个对应的组件对象。隐式的用this指针进行了代替,获得这个对象的组件,否则使用其他gameObject调用就是其他的组件啦
// 获取transform组件
Debug.Log(transform.position);
// 获取其他的组件,用模板的方式来获得对象
BoxCollider bc = GetComponent<BoxCollider>();
添加组件
注意这个只有编辑器运行时候才可以创建出来这个组件,如果是这样创建的话,我认为必需要在代码里做好相应的初始化,毕竟脚本也是运行时产生的结果
// 添加一个组件
gameObject.AddComponent<AudioSource>();
获取组件
通过名字,名字是全匹配,或者按照标签来找到这个对象。
GameObject test = GameObject.Find("Test");
GameObject test2 = GameObject.FindWithTag("Test");
生成预设体
我当时就在想,如果需要多个预设体总不能一直让我拖来拖去吧,不累死我,按照vue框架也是一个v-for循环进行渲染。跟生成gameObject一个套路,先定义一个对象,然后把预设体的组件拖过来,然后进行绑定,最后调用Instantiate这个函数生成一个预设体实体
// 生成一个预设体实体
Instantiate(myPrefab);
空空如也
运行时就可以出现啦,我们使用代码创造的预设体实体
上一帧到这一帧的时间
这个API接口调用即可
Debug.Log(Time.deltaTime);
Application 类
Application 类有些文件的操作,这些操作感觉我想做的游戏用不到这个,简单了解一下。毕竟不是单机不可能把东西存到客户端这一侧的。
设置后台运行
这个参数还是蛮有用的,游戏小窗后是否可以运行
Application.runInBackground
打开url
没想到这个类还可以运行url,牛逼!
Application.OpenUrl
还可以设置退出游戏
执行这个函数直接退出游戏
Application.Quit()
场景,这个感觉很重要
场景管理类
SceneManager
场景跳转/场景加载
演示的代码是把这个物体上,想了想也很合理,相当于有一个类似传送门的东西,当走到传送门,调用这个函数然后进行场景的跳转。
SceneManager.LoadScene("MyScene");
打开文件->生成设置,填场景名字和跳转的这个索引ID都可以,但我认为名字一般不会轻易的变动,但这个出场的顺序很容易变动,容易改错了,所以我觉得应该使用场景名字比较好
保留原来的场景
// 加载的时候加参数就好了
SceneManager.LoadScene("MyScene",LoadSceneMode.Additive);
场景信息获取
// 获取当前场景
Scene sc = SceneManager.GetActiveScene();
Debug.Log(sc.name);
// 场景是否被加载了
Debug.Log(sc.isLoaded);
// 场景路径
Debug.Log(sc.path);
// 场景索引
Debug.Log(sc.buildIndex);
场景创建
SceneManager.CreateScene("codeCreatScene");
当前加载场景的数量
Debug.Log(SceneManager.sceneCount);
异步加载
StartCoroutine 相当于开了个协程,也不是封装好的,还是需要手动调用
AsyncOperation op;
// Start is called before the first frame update
void Start()
{
// 这就算开启了另一个协程
StartCoroutine(loadScene());
}
// 协程方法
IEnumerator loadScene()
{
op = SceneManager.LoadSceneAsync(1);
yield return op;
}
场景加载条
就是简单使用AsyncOperation 这个类
Debug.Log(op.progress);
transform 组件
前方是z轴,右方是x轴,上方是y轴
获取常用信息
// 获取世界位置
Debug.Log(transform.position);
// 获得在父物体中的位置
Debug.Log(transform.localPosition);
// 获取旋转
Debug.Log(transform.rotation);
Debug.Log(transform.localRotation);
// 旋转的角度
Debug.Log(transform.localEulerAngles);
// 获取缩放
Debug.Log(transform.localScale);
// 向量位置获取
// 前方
Debug.Log(string.Format("forward:{0}",transform.forward));
一些api
一定要清楚一点unity的坐标系
// 正前方,也就是x轴看向的点
transform.LookAt(Vector3.zero);
// 绕着某一点和一个轴进行旋转
transform.RotateAround(Vector3.zero, Vector3.up, 0.5f);
// 移动
transform.Translate(Vector3.forward * 0.01f);
查找父子关系
就是要transform类来找到父元素的gameObject的
transform.parent.gameObject;
// 判断是否是子元素
bool res = transform.IsChildOf(fa.transform);
小结一下,gameObject和transform这两个类很重要,一个可以找到游戏的物体,一个可以找到对应的父子关系
如标题所示