unity汇总

2021/07/18 program 共 8591 字,约 25 分钟

编辑器操作

  • 放大恢复窗口 shift + space

  • 窗口布局:window - layout 进行选择,恢复默认选择: default

  • w q e r t y u w - 调整方向 transform - reset 还原

  • - sorting layer调整画面图层的显示序列。可以认为是把图层分类。

  • sorting layer越在下面,越在前面order layer 数字越大越在前2dobject - sprite

  • c#代码编辑器设置:unity edit - preferences - external tools 把script editor 默认的 open by file extention 改成 visual stdio2019

  • 会在unity编辑器的左下角看到输出在玩游戏时修改参数时,要在齿轮里点 copyComponent

  • 设置Layer层

    菜单:Edit / Settings / Tags and Layers / Layers 在这里插入图片描述

    设置Tags

    菜单:Edit / Settings / Tags and Layers / Tags 在这里插入图片描述

素材

素材资源下载

在线素材商店选素材,学习的话可以先选择一些免费的素材,然后点「添加至我的资源」。

在unity editor里,找到菜单:Window - Package Manager - 下拉列表切换到My Assets,刷新就能出来选择的资源了,下载到本地即可使用。

资源处理

图片的Pixel Per Unit默认是100像素,如果图片的像素不高的话,可以设置一个较小的值,例如16。

切图

如果是多图资源拼合而成,需要切图,切图有自动切图和手动切图。

sprite editor sprite mode -multiple //Slice- autoslice - slice Slice - grid by cell size 16,16 apply

预制体prefab

创建一个Perfabs防止重复利用 object

动画

使用序列帧创建动画

动画状态切换

  • 添加站立动画Idle,跑动动画Run。
  • 了解 Animator 和 Animation 的使用。
  • 在 C# 脚本里调用动画效果。
  • 跳跃和下落的动画转换
  • LayerMask的使用方法

添加文件夹 Assets - Animation - Player create AnimationController window - Animation - Animation 打开动画面板 Smaples 设置动画速率

window - Animation - Animator parameters 设置变化参数

修改变化箭头 去掉 Has Exit Time Transition Duration 设置成 0

将Player Animation 加到 Player 编辑变化代码 public Animator anim; anim.SetFloat(running, Mathf.Abs(facedirection));

UGUI

canvas

切换成camera,然后把主camera拖进来。

控件响应鼠标


鼠标滑过放大效果

TileMap

创建TileMap

create - 2dobject - tilemap

Unity之Tilemap - boynextdoor♂ - 博客园

还需要创建一个调色板,可以理解为用来「贴瓷砖」的画笔。

window - 2d - tile palette

tilemap画的地图有缝隙要怎么解决?

选择grid 在右边的inspector窗口里 把Grid的Grid Size X和Y都改成0.99

Tilemap Collider 2D

*正确的解决移动卡顿问题应该在Tilemap上添加 Composite Collider2D 组件,勾选 Tilemap Collider2D 组件中的 Use Composite,将自动添加上的 Rigidbody2D 组件的 Body Mode 改为 Static

Tilemap加碰撞体

  1. 添加Tilemap Collider 2D组件
  2. 如果想要将所有的碰撞体组合成一个,再添加Composite Collider 2D组件,但是这样会自动给物体添加刚体,把Body Type变为static物体就不会因重力影响而下落。并在Tilemap Collider 2D中选中Used by composite.

动态创建Tile

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

public class MapEditor : MonoBehaviour
{
    public Tilemap tilemap;//引用的Tilemap,加入脚本后需要将对应tilemap拖进来
    private Dictionary<string, Tile> arrTiles; //地块种类
    private List<string> TilesName;
    string[] TileType;
    //大地图宽高
    public int levelW = 10;
    public int levelH = 10;
    // Start is called before the first frame update
    void Start()
    {
        arrTiles = new Dictionary<string, Tile>();
        TilesName = new List<string>();
        InitTile();
        InitMapTilesInfo();
        InitData();
    }

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

    void InitData()
    {
        for (int i = 0; i < levelH; i++)
        {//根据地面类型TileType初始化tilemap
            for (int j = 0; j < levelW; j++)
            {
                tilemap.SetTile(new Vector3Int(j, i, 0), arrTiles[TileType[i * levelW + j]]);
            }
        }
    }

    void InitMapTilesInfo()
    {
    	//初始化地图信息,即每个单位对应的地面类型
        TileType = new string[levelH * levelW];
        for (int i = 0; i < levelH; i++)
        {
            for (int j = 0; j < levelW; j++)
            {
                TileType[i*levelW+j] = TilesName[Random.Range(0, TilesName.Count)];
            }
        }
    }

    void InitTile()
    {
        //创建3钟类型的地面瓦片
        AddTile("soil", "Image/soil");
        AddTile("brick", "Image/brick");
        AddTile("grass", "Image/grass");
        
    }

    void AddTile(string labelName,string spritePath)
    {
        Tile tile = ScriptableObject.CreateInstance<Tile>();//创建Tile,注意,要使用这种方式
        Sprite tmp = Resources.Load<Sprite>(spritePath);
        tile.sprite = tmp;
        arrTiles.Add(labelName, tile);
        TilesName.Add(labelName);
        
    }
}
Tile[] arrTiles;//生成的Tile数组

arrTiles = new Tile[colorCount];
for(int i=0;i<colorCount;i++){
    arrTiles[i] = ScriptableObject.CreateInstance<Tile>();//创建Tile,注意,要使用这种方式
    arrTiles[i].sprite = baseTile.sprite;
    arrTiles[i].color = new Color(Random.Range(0f, 1f), Random.Range(0f,1f), Random.Range(0f, 1f), 1);
}
for(int i=0;i<levelH;i++){//这里就是设置每个Tile的信息了
    for(int j=0;j<levelW;j++){
        tilemap.SetTile(new Vector3Int(j, i, 0), arrTiles[Random.Range(0, arrTiles.Length)]);
    }
    yield return null;
}

将鼠标坐标转成世界坐标,注意要z轴

 Vector3 wordPosition  =  Camera.main.ScreenToWorldPoint(mousePosition);

然后调用Tilemap的 WorldToCell 函数,就可以拿到一个地图中的坐标

 Vector3Int cellPosition 
 = 
 backMap.
 WorldToCell(
 wordPosition);

最后就直接设置Tile了

 backMap.
 SetTile(
 cellPosition, 
 gameUI.
 GetSelectColor().
 colorData.
 mTile);

实现当tilemap里面的格子与其他的对象发生碰撞后,消除碰撞的那个格子

//tilemap就是发生碰撞的tilemap对象
void OnCollisionEnter2D(Collision2D collision)
    {
        Vector3 hitPosition = Vector3.zero;
        if (tilemap != null && tilemapGameObject == collision.gameObject)
        {
            foreach (ContactPoint2D hit in collision.contacts)
            {
                hitPosition.x = hit.point.x - 0.01f * hit.normal.x;
                hitPosition.y = hit.point.y - 0.01f * hit.normal.y;
                tilemap.SetTile(tilemap.WorldToCell(hitPosition), null);
            }
        }
    }

要从图块贴图的矩形区域获取包含所有图块的数组,请使用tilemap.GetTilesBlock(BoundsInt bounds)。您将获得一维拼贴块,因此您需要自己知道下一排拼贴块何时开始。任何空单元格都将用一个null值表示。

如果需要所有图块,请使用tilemap.cellBounds。这将为您提供一个BoundsInt覆盖tilemap完整使用区域的对象。这是一个示例脚本,该脚本从同一个游戏对象上的Tilemap中获取所有图块,并列出其图块及其坐标:

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

public class TileTest : MonoBehaviour {
    void Start() {
        Tilemap tilemap = GetComponent<Tilemap>();

        BoundsInt bounds = tilemap.cellBounds;
        TileBase[] allTiles = tilemap.GetTilesBlock(bounds);

        for (int x = 0; x < bounds.size.x; x++) {
            for (int y = 0; y < bounds.size.y; y++) {
                TileBase tile = allTiles[x + y * bounds.size.x];
                if (tile != null) {
                    Debug.Log("x:" + x + " y:" + y + " tile:" + tile.name);
                } else {
                    Debug.Log("x:" + x + " y:" + y + " tile: (null)");
                }
            }
        }
    }
}

这是另一种方法 .cellBounds.allPositionsWithin

public Tilemap tilemap;
public List<Vector3> tileWorldLocations;

// Use this for initialization
void Start () {
    tileWorldLocations = new List<Vector3>();

    foreach (var pos in tilemap.cellBounds.allPositionsWithin)
    {   
        Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z);
        Vector3 place = tilemap.CellToWorld(localPlace);
        if (tilemap.HasTile(localPlace))
        {
            tileWorldLocations.Add(place);
        }
    }

    print(tileWorldLocations);
}

c# - How can I change a sprite used for a Unity Tilemap tile at runtime? - Game Development Stack Exchange

Change Unity Tilemap’s Tile sprite during runtime

高亮

 //This line outside the Update 
  TileBase highlightTile = gravelTile;
  
  
  void Update() { 
        
      Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
      Vector3Int tileCoordinate = highlightMap.WorldToCell(mouseWorldPos);
  
      if(tileCoordinate != previousTileCoordinate ){
          highlightMap.SetTile(previousTileCoordinate, null);
          highlightMap.SetTile(tileCoordinate,highlightTile);
          previousTileCoordinate = tileCoordinate;     
      }
  }

Physics2D

刚体

禁止物体旋转:Rigidbody 2D–Constraints–Freeze Position Z打钩

Collider

输入

edit - projectsetting - input Horizontial 横向

add Component new script

Assets - Script - 放代码 script文件还要手动拖到对应Sprite里

移动时会触发Update() 函数 public Rigidbody2D rb; //定义刚体,手动在图形编辑器里拖进去 Input.GetAxis(Horizontal);// 获取横轴变更 rb.velocity = new Vector2(horizontalMove * speed, rb.velocity.y); //设置对象位置

将刚体 Constrants 里的 z 勾选,让它不会飞起来

scale 控制方向 float facedirection = Input.GetAxisRaw(Horizontal); //直接获得 -1,0,1 获取整数 transform.localScale = new Vector3(facedirection, 1, 1);// 设置方向

保证不同帧率正常 Update 函数改为 FixedUpdate() 函数 rb.velocity = new Vector2(horizontalMove * speed * Time.deltaTime, rb.velocity.y); //速度乘以一个时间参数

跳跃 Input.GetButtonDown(Jump) // 获取跳跃按键 rb.velocity = new Vector2(rb.velocity.x, jumpforce * Time.deltaTime); //改变y轴方向 Rigidbody2D 中的GravityScale 参数同样可以调整跳跃力度

拾取效果 在 PlayerController void OnTriggerEnter2D(Collider2D collision) 方法里

镜头

- 镜头跟踪。 - 初步了解Cinemachine。

添加CameraController控制镜头

2.填加Cinemachine控制镜头 添加插件 window-PackageManager-Cinemachine 对背景添加 Polygon Colider2d 勾选isTriger Cinemachine Confiner 填入 Polygon

Lens- Orthographic Size 镜头大小

代码片段

通过名字找物体

GameObject.Find("Player")

通过名字寻找物体子集

transform.FindChild("物体子集名字")

显示和隐藏物体

gameObject.SetActive(true);  

使用和关闭物体代码

gameObject.GetComponent<代码名字>().enable=true;




按下动画事件 if (Input.GetMouseButton(0))
按下事件   if (Input.GetMouseButtonDown(0))
抬起事件   if (Input.GetMouseButtonUp(0))

销毁一样标签的物体

GameObject [] objs = GameObject.FindGameObjectsWithTag("标签名");
foreach(GameObject obj in objs){
       Destroy(obj);
}

物体水平匀速移动

transform.Translate(-0.1f*Time.deltaTime,0,0);

位置相关的: 5个和位置相关的Vector3类型变量 up 表示世界坐标的Y轴方向 right 表示世界坐标的X轴方向 forward 表示世界坐标的Z轴方向 position 表示对象在世界坐标系中的位置 localPosition 表示对象相对父节点变换的坐标位置

改变物体颜色

obj.renderer.material.color=Color.red

父子节点相关的: parent 变量表示Transform的父节点 Transform Find(string name) 根据名字查找子节点 bool IsChildOf(Transform node) 判断该Transform是否某Transform的子节点 void DetachChildren() 解除所有子节点的父子关系

鼠标:

Input.mousePosition表示鼠标当前的像素位置(坐标系如何?以左下角为原点)

接下来这三个函数的参数,0左键,1右键,2中键
GetMouseButton 对应的键处于按下状态时返回true
GetMouseButtonDown 对应的键被按下时返回true
GetMouseButtonUp 对应的键弹起时返回true
OnMouseDown 当鼠标点击到对象的时候回调
OnMouseDrag 当鼠标拖拽对象时调用,在Ignore Raycast层上无效
OnMouseEnter 当鼠标进入对象时调用
OnMouseExit 当鼠标离开对象时调用
OnMouseOver 当鼠标停留在对象上面时调用
OnMouseUpAsButton 鼠标在同一个对象上按下,并弹起时调用
OnMouseUp 跟楼上一样
gameObject.transform.rotation = new Quaternion (Player.transform.rotation.x, Player.transform.rotation.y, Player.transform.rotation.z, Player.transform.rotation.w);

gameObject和Player旋转角度一样!

俩个物体之间的距离 float Distance

float Distance = Vector3.Destance(position1,position2);

如果玩家和敌人的距离小于10,执行{}代码

if( Vector3.Destance(敌人.position,玩家.position)<10f){
     //  执行相应代码
}

18.Animation动画

01.倒回播放 Animation.Rewind();

02.停止所有动画 Animation.Stop();

停止动画 Animation.Stop(“动画名字”);

03.使用动画循环模式 Animation.WropMode= WropMode.loop;

04.等待动画播放完成 animation.Play();     yiel WaitForSeconds (animation.Clip.Length);

05.打印动画长度 print(animation["动画名字"].Length);

参考

文档信息

Search

    Table of Contents