u3d&&blender&&unity3d

发布为webgl时候报错

报错内容

Unable to parse Build/RobotTest.framework.js.gz! This can happen if build compression 
was enabled but web server hosting the content was misconfigured to not serve the file 
with HTTP Response Header "Content-Encoding: gzip" present. Check browser 
Console and Devtools Network tab to debug.

修改设置

项目模板

Unity3D URP管线是Unity在2019年推出的一种轻量级渲染管线。它是对Unity内置管线的改进和优化,主要针对移动设备和低端硬件的性能优化。Unity3D URP管线的主要特点如下:

轻量级:Unity3D URP管线相较于Unity内置管线,更加轻量级,可以在移动设备和低端硬件上运行更流畅。

可高度自定义:Unity3D URP管线提供了高度自定义的渲染流程,开发者可以根据需求自由定制渲染效果。

渲染质量较低:由于轻量级的特性,Unity3D URP管线在渲染质量上相对较低,无法实现Unity内置管线中的一些高级渲染效果。

Unity内置管线是Unity3D最早推出的渲染管线,也是最常用的一种。它提供了一套完整的渲染功能,适用于大多数的游戏开发需求。Unity内置管线的主要特点如下:

渲染质量较高:Unity内置管线在图形渲染方面有着较高的质量,可以实现较为真实的光照和阴影效果。

功能丰富:Unity内置管线提供了多种渲染功能,如透明效果、反射效果、抗锯齿等,可以满足不同游戏的需求。

灵活性较低:Unity内置管线的渲染流程是固定的,开发者无法自定义渲染流程。

单位与参考

默认情况下,一个cube的长宽高为1x1x1,可以视做为现实物体的1米,既一个人为2个单位,以此类推来确定物体的高度,受重力影响,默认情况下,我们可以增加地形或一个plan,可以理解为平面和地板,可以阻止物体下落到的游戏之外。

而大多数物体(至少内置的几个基础组件中)的position的中心点在对象最中间,因此,当物体的position的Y设置为0时,物体会穿透到地板地板之外,此时需要调整物体Y以适应物体在相对位置上

由于u3d的脚本需要绑定到一个GameObject,通常会放置一个胶囊Cylinder,胶囊的默认高度为2,同样道理,需要将胶囊的Y提升到对应的高度以适应屏幕

组织项目结构

默认情况下,u3d只生成了scene文件夹,并生成了一个默认场景,资源文件一股脑的全部丢在这个文件夹,资源管理,复制类的重用非常不方便。

可以按一个独立模块来管理资源

例如:

|Assets
|--welcome
|----scripts
|----assets
|------video
|------material
|--skybox
|----FS003
|--ui
|--level-A
|----assets
|------video
|------material
|----scripts
  

使用资源和插件

VSCODE扩展

资源网站

直接打开:https://assetstore.unity.com/ 或者在unity3d软件点击 window > asset store

常用资源

Odin:编辑器增强,为cs脚本增加attribe后,在编辑器更好的使用(淘宝有售),https://assetstore.unity.com/packages/tools/utilities/odin-inspector-and-serializer-89041

角色控制器(暂时不知道怎么用的): https://assetstore.unity.com/packages/3d/characters/modular-first-person-controller-189884

XCharts:https://github.com/XCharts-Team/XCharts

https://assetstore.unity.com/packages/3d/environments/landscapes/terrain-sample-asset-pack-145808 https://assetstore.unity.com/packages/p/grass-flowers-pack-free-138810

Fantasy Skybox FREE:https://assetstore.unity.com/packages/2d/textures-materials/sky/fantasy-skybox-free-18353

https://assetstore.unity.com/packages/2d/textures-materials/water/simple-water-shader-urp-191449

https://assetstore.unity.com/packages/3d/vegetation/trees/mobile-tree-package-18866 https://assetstore.unity.com/packages/3d/vegetation/trees/realistic-tree-9-rainbow-tree-54622

摄像机&&主灯光&&基础场景

在大多数45度伪3D场景下的摄像机与灯光的最佳参数为:

默认视角

摄像机

摄像机的Z轴指向物体

主灯光

光照角度的X轴影响被照射物体

此时,物体的阴影在物体左侧,如果按平面上北下南,左西右东,应该属于上午

如果要物体的阴影在物体右侧,则设置为

创建天空

创建材质

免费材质下载链接

https://assetstore.unity.com/packages/2d/textures-materials/sky/fantasy-skybox-free-18353

下一步:创建地形

https://qq829.cn/book/books/u3dblend/page/26e35

第三人称控制

必要插件(官方内置插件)

开始使用

此两个步骤可以省略,只是示意一下这是一个任务角色

虽然调整lookme的position也可以控制摄像机的视角,但是还是应该调整Third Person Camera,因为lookme与被跟随的物体不在一个中心点的话,会导致跟随非常奇怪,无法使角色一直在正中间。最终得到的效果如下:

增加鼠标和键盘控制

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

public class ThirdPersonCameraLook : MonoBehaviour
{
    private GameObject mainCamera;

    [Header("Cinemachine")]
    [Tooltip("跟随目标")]
    public GameObject CameraTarget;

    [Tooltip("向上的最大角度")]
    public float TopClamp = 70.0f;

    [Tooltip("向下的最大角度")]
    public float BottomClamp = 0.0f;

    [Tooltip("相机旋转速度")]
    public float RotationSpeed = 1.0f;

    // 输入阈值
    private const float threshold = 0.01f;
    // 相机目标的 Y 轴旋转角度
    private float cinemachineTargetYaw;
    // 相机目标的 X 轴旋转角度
    private float cinemachineTargetPitch;
    // 存储玩家输入的视角变化
    private Vector2 lookup;
    // 标记是否正在旋转
    private bool isRotateing = false;
    void Start()
    {
        if (mainCamera == null)
        {
            // 查找并存储主相机对象
            mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
        }
        // 初始化相机目标的 Y 轴旋转角度
        cinemachineTargetYaw = CameraTarget.transform.rotation.eulerAngles.y;
    }

    // Update is called once per frame
    void Update()
    {
        // 检查鼠标右键是否按下
        isRotateing = Mouse.current.rightButton.isPressed;
        // 如果正在旋转且输入的平方长度大于等于阈值,则更新相机目标的旋转角度
        if (isRotateing && lookup.sqrMagnitude >= threshold)
        {
            cinemachineTargetYaw += lookup.x;
            cinemachineTargetPitch += lookup.y;
        }
        // 限制相机目标的旋转角度在合理范围内
        cinemachineTargetYaw = ClampAngle(cinemachineTargetYaw, float.MinValue, float.MaxValue);
        cinemachineTargetPitch = ClampAngle(cinemachineTargetPitch, BottomClamp, TopClamp);

        // 使用插值函数平滑过渡相机的旋转,如果同时加了移动组件,不建议使用平滑旋转
        // Quaternion targetRotation = Quaternion.Euler(cinemachineTargetPitch, cinemachineTargetYaw, 0.0f);
        // CameraTarget.transform.rotation = Quaternion.Lerp(CameraTarget.transform.rotation, targetRotation, Time.deltaTime * RotationSpeed);
        // 控制相机的旋转
        CameraTarget.transform.rotation = Quaternion.Euler(cinemachineTargetPitch, cinemachineTargetYaw, 0.0f);
    }
    // 限制角度在指定范围内
    private static float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360.0f)
        {
            angle += 360.0f;
        }
        if (angle > 360.0f)
        {
            angle -= 360.0f;
        }
        return Mathf.Clamp(angle, min, max);
    }

    public void OnLook(InputValue value)
    { // 处理玩家输入的视角变化
        lookup = value.Get<Vector2>();
    }
}


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

public class ThirdPersonCameraMove : MonoBehaviour
{

    // 主摄像机对象引用
    private GameObject mainCamera;
    // 角色控制器对象引用
    private CharacterController controller;

    // 移动输入值
    private Vector2 moveValue;

    //   移动速度
    [Tooltip("移动速度")]
    public float speed = 1.0f;
    // 目标旋转角度
    private float targetRotation = 0.0f;

    // 平滑旋转时间
    public float RotationSmoothTime = 0.1f;
    // 旋转速度
    private float rotationVelocity = 0.0f;

    void Start()
    {
        if (mainCamera == null)
        {
            mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
        }
        // 获取角色控制器对象
        controller = GetComponent<CharacterController>();
    }


    void Update()
    {
        // 记录原始的Y方向数值
        Vector3 velocity = new Vector3(0, -1, 0);
        if (moveValue != Vector2.zero)
        {
            // 计算输入方向,转换为世界坐标
            Vector3 inputDir = new Vector3(moveValue.x, 0.0f, moveValue.y).normalized;
            // 计算目标旋转角度
            targetRotation = Mathf.Atan2(inputDir.x, inputDir.z) * Mathf.Rad2Deg + mainCamera.transform.eulerAngles.y;

            // 平滑旋转
            float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref rotationVelocity, RotationSmoothTime);
            // 旋转角色
            transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
            // 计算移动方向
            Vector3 targetDir = Quaternion.Euler(0.0f, targetRotation, 0.0f) * Vector3.forward;
             // 记录原始的Y方向数值
            velocity += targetDir.normalized * (speed * Time.deltaTime);
            // 移动角色
            // controller.Move(targetDir.normalized * (speed * Time.deltaTime));
        }
    }

    void OnMove(InputValue inputValue)
    {
        moveValue = inputValue.Get<Vector2>();
    }

}

使用视频

如果场景中的内容全部使用模型渲染,除了耗费性能,还额外增加l很多工作。如果使用视频,则可以省却很多事情

使用视频播放器

四种渲染方式

可以将同一个摄像机关联到2个Video上,一个设置为远景模式,一个设置为近景,调整不同的alpha通道,实现一些特效效果

使用视频作为场景过度

可以播放一个前景视频,作为启动动画或者场景切换动画,然后切换到另外的场景

https://qq829.cn/book/books/u3dblenderunity3d/page/01161

场景&&场景切换

一个scene就是一个场景(关卡),打开file->build Settings,将场景添加到scenes in build中,拖拽排序,第一个场景为游戏启动的默认场景,

多个场景之间切换代码如下

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

public class LoadScreen : MonoBehaviour
{
    // 暂时还不清楚这个名字不在scenes文件夹或者在子文件夹会有什么影响
    public string SceneName = "SampleScene";
    // 延迟时间
    public float Delay = 5f;
    void Start()
    {
        // 5秒后自动切换场景
        StartCoroutine(ChangeSceneAfterDelay(Delay));
    }
    // 切换场景
    private IEnumerator ChangeSceneAfterDelay(float delay)
    {
        // 等待delay秒
        yield return new WaitForSeconds(delay);
        // 切换场景
        UnityEngine.SceneManagement.SceneManager.LoadScene(SceneName);
    }
    void Update()
    {

    }
}

后台运行

默认情况下,游戏到后台后就停止运行了,要设置在后台运行

菜单Edit->Project Settings->Player,右边的Resolution and Presentation选项卡中将Run In Background勾上

用户界面和UI系统

u3d有2个UI系统,一个是传统的UGUI,一个是UI TOOL KIT,现在网上大部分教程都是UGUI的,而且UGUI主要以图片为主,可以做出更好看的效果,本文也使用UGUI

开始

为便于观察,可以将编辑器设置为2D模式

在层级管理器上右键->ui->canvas,此时编辑器将自动增加一个EventSystem,EventSystemy用于处理输入事件。

也可以直接增加一个image控件,编辑器也会自动帮忙增加canvas和Eventy System,所有的UI组件实际上都扩自image,可以在image上增加组件,此时,这个image就变成了一个按钮,可以处理按钮事件了。

使用中文字体

window->TextMeshPro->Font Assets Creator

注意character set 选择characters from file,并在项目创建一个txt文件,文件编码为utf8,把你需要使用的文字输入进去,即默认不会有文字

x想要获得得更清晰的显示效果,可以选择Render Mode****SMOOTH_HINTED,默认是SDFAA生产速度最快,但是显示效果一般

然后点击Generate Font atlas生成,最后点击保存,即可以使用中文字体了

处理按钮事件

新增一个脚本UiEvents.cs,新建一个GameObject, 并将脚本挂载上去,回到button上,附件相关事件

public class UiEvents : MonoBehaviour
{

    public void OnBtnStartGanmeClick()
    {
        Debug.Log("Button Clicked");
    }
}

使用布局系统

使用锚点确定对其方式,可以按照我们常见的布局模式,使用Panel先画出区块,例如top,left,以适用自适应

使用Panel先画出区块,例如top,left,以适用自适应

增加一个GameObject,增加组件,搜索Layout,根据需要,选择网格布局、垂直布局、水平布局

常用组件

组件由Background(未选中状态),Checkmark(选中状态),Label(文字)三部分组成,可以分别设置单独的背景实现效果

组件由三部分组成:Background(背景),Handle(滑块),Fill(填充)组成,既在最左边时,全部是背景,随着向右滑动,填充fill

注意事项

如果提示说新老版本的input system不兼容,需要在EventSystem上执行相关操作

模型&&材质&&贴图

和真实世界一样,物体由骨架(框架)、蒙皮、喷涂组合而来

使用photoshop绘制材质贴图

使用PS生成连续图
使用PS生成法线图
使用PS生成立方体贴图

其他软件

创建地图

安装地图扩展工具

window > package manager 搜索 terrain tools ,安装地图编辑器扩展工具

增加地图

GameObject > 3D Object > Terrain

对地图进行设置

3d里面并没有一个固定的单位,有的仅是相对单位,例如一个立方体的高度为1,假设一个人的身高大约2米,可以根据此来换算地图的大小,地图的默认大小是1000,太大的地图消耗性能

terrain width:地图宽,X方向大小 terrain lenght:地图的长,Y方向大小 terrain height:视乎并没有用

使用地形工具进行绘制

植树

调整画刷大小和密度,密度太小可能种不下去,密度太大会选的很杂乱

种花

与植树大同小异,好处是可以同时种几种

设置雾

粒子&&特效&&particle system

学习视频

https://www.bilibili.com/video/BV1yy4y1B7ir/?vd_source=e5c89a4572347dbc9fec6b7a7ef56513

增加particle system

右键 > effects > particle system

为了更便于观察,可以去掉selection outline

基础使用

默认会有三个组件被选中,因为默认情况下在编辑器窗口不会自动预览,需要选择后才能预览,比较复杂的效果由多个效果组成,使用空组件也不能生效,可以先创建一个particle system,然后将默认的三个组件去掉,选中父组件,即可用预览

shader&&着色器

什么是shader

3D世界物的显示与增加方式为步骤为:网格 > 材质 > 贴图

其中在材质步骤有诸多设置参数,其中一项重要选型为shader,既着色器,以告诉物体应该如何绘制,3D软件通常内置了很多shader,当内置shader无法满足我们要求的时候,需要自己实现shader

为模型增加材质,通常可以:

双击材质,既可以查看材质的相信情况

当默认shader无法满足我们要求时,例如特殊,则我们需要自己定义shader

创建shader

create > shader graph > URP > lit shader graph

双击新建的shader文件,则进入shader编辑窗口,保存shader后(不保存的在选择界面看不到),可以在材质的shader选项选择当前自定义shader

shader > shader graphs > new-cus-shaper

开始编辑自定义shader

shader的主要工作流程如下,其工作原理为,3D物体在计算机进行显示的时候,总是需要将物体转换为具体的颜色信息输入到显示卡,通过对一系列的参数进行计算后,最终改变主要影响物体的两个主要参数

各面板情况

常用技巧

xcharts&&图表插件

下载地址

https://github.com/XCharts-Team/XCharts

折线图

主要指需要如上两个即可,其他的可以通过设置属性改变线条样式

可以通过 Line Stype -> Type修改线条样式

可以通过设置 Line Type设置,是曲线变成平滑曲线

可以通过设置 Line Type设置,是曲线变成平滑曲线

柱状图

实际上指需要如上两个即可,其他d可以通过调整Bar Type修改柱子样式

可以通过修改Bar Type修改柱子样式

饼图

雷达图

xcharts样式设置-折线图

主要可自定义样式区域

Area Style

线条样式

半透明背景

鼠标悬停提示

{.}{b}年:{c}万元

/// ||提示框标题内容的字符串模版格式器。支持用 \n 换行。可以单独设置占位符{i}表示忽略不显示title。
/// 模板变量有{.}、{a}、{b}、{c}、{d}、{e}、{f}、{g}。<br/>
/// {.}为当前所指示或index为0的serie的对应颜色的圆点。<br/>
/// {a}为当前所指示或index为0的serie的系列名name。<br/>
/// {b}为当前所指示或index为0的serie的数据项serieData的name,或者类目值(如折线图的X轴)。<br/>
/// {c}为当前所指示或index为0的serie的y维(dimesion为1)的数值。<br/>
/// {d}为当前所指示或index为0的serie的y维(dimesion为1)百分比值,注意不带%号。<br/>
/// {e}为当前所指示或index为0的serie的数据项serieData的name。<br/>
/// {h}为当前所指示或index为0的serie的数据项serieData的十六进制颜色值。<br/>
/// {f}为数据总和。<br/>
/// {g}为数据总个数。<br/>
/// {y}为value所对应的y轴的类目值。<br/>
/// {.1}表示指定index为1的serie对应颜色的圆点。<br/>
/// {a1}、{b1}、{c1}中的1表示指定index为1的serie。<br/>
/// {c1:2}表示索引为1的serie的当前指示数据项的第3个数据(一个数据项有多个数据,index为2表示第3个数据)。<br/>
/// {c1:2-2}表示索引为1的serie的第3个数据项的第3个数据(也就是要指定第几个数据项时必须要指定第几个数据)。<br/>
/// {d1:2:f2}表示单独指定了数值的格式化字符串为f2(不指定时用numericFormatter)。<br/>
/// {d:0.##} 表示单独指定了数值的格式化字符串为 0.## (用于百分比,保留2位有效数同时又能避免使用 f2 而出现的类似于"100.00%"的情况 )。<br/>
/// 示例:"{a}:{c}"、"{a1}:{c1:f1}"、"{a1}:{c1:0:f1}"、"{a1}:{c1:1-1:f1}"

使用代码填充数据


public class LoadData : MonoBehaviour
{
    private Color initialColor = Color.white;
    private Color targetColor = Color.white;
    private Color currentColor = Color.white;
    public float updateInterval = 1.0f;
    private XCharts.Runtime.LineChart lineChart;
    [Title("目标对象")]
    public GameObject TargetObject;


    // Start is called before the first frame update
    void Start()
    {
        if (TargetObject != null)
        {
            // 根据tag查找对象
            lineChart = TargetObject.GetComponent<XCharts.Runtime.LineChart>();
            lineChart.ClearData();
            lineChart.AddXAxisData("2020");
            lineChart.AddXAxisData("2021");
            lineChart.AddXAxisData("2022");
            lineChart.AddXAxisData("2023");
            lineChart.AddXAxisData("2024");

            lineChart.AddData(0, 0, 100);
            lineChart.AddData(0, 1, 60);
            lineChart.AddData(0, 2, 15);
            lineChart.AddData(0, 3, 30);
            lineChart.AddData(0, 4, 77);

            // 初始化颜色
            initialColor = new Color(1.0f, 0.0f, 1.0f); // 紫色
            currentColor = initialColor;
            targetColor = new Color(1.0f, 1.0f, 1.0f); // 白色
        }

    }

    // Update is called once per frame
    void Update()
    {
        if (lineChart != null)
        {
            // 渐变修改series上的item style的background color
            var serie = lineChart.GetSerie(0);
            if (serie != null)
            {
                var itemStyle = serie.itemStyle;
                float time = Mathf.PingPong(Time.time / updateInterval, 1.0f);
                currentColor = Color.Lerp(initialColor, targetColor, time);
                itemStyle.backgroundColor = currentColor;
                serie.itemStyle = itemStyle;
            }
        }
    }
}


xcharts样式设置-柱状图

为单独的柱子设置样式

动画不起效果

柱状图直接修改Item Style后发现需要把鼠标放到图表上才起效果

blender基本操作

快捷键

恢复默认布局

文件(file)->默认(defaults)->加载初始设置(load factory settings) , 字体太小看不清,设置分辨率缩放。恢复默认设置后,中文汉化不完整,需要重新启动blender.

blender建筑插件&&building_tools

https://github.com/ranjian0/building_tools

使用方法

https://www.bilibili.com/video/BV1DQ4y1d7BT/

blender uv和贴图

先为模型展UV

先增加UV贴图(默认情况下应该已经有一张了)

点击基础色的小点

选择图像纹理

选择新建或者打开一张已经存在的纹理图

方法二,打开UV编辑器,选择图像,新建,建议选择彩色栅格图,此时回到上一步,既可以选择到UV图片了

可以选择这里将UV图片断开

此时已经可以看到附加的默认纹理背景了,主要需要把材质预览模式打开

打开纹理绘制窗口,可以直接在模型或者纹理上面进行画刷涂改,但是这个时候不方便,可以使用参考图进行绘制。在纹理窗口,加载一张片,作为画刷

修改不同纹理参数,实现不同的效果涂抹,进行画刷涂抹,但是这图片适合高度重复的情况,例如草地,墙面等。可以修改必刷的纹理为镂版,

设置外部编辑器为Photoshop

blender室内建筑&&Archimesh

安装插件

使用方法一

打开面板

导入户型图,进行临摹,调整墙面的长度、角度等

增加屋顶的小尖尖

制作屋顶瓦面

然后添加们和窗口

使用方法二

使用标注工具初步画出一个框框

一键生成,然后调整

blender室内建筑插件&&ArchiPack

插件介绍

插件名称

使用方法

调出工具箱