分类: Unity

  • 2021.1.25 公司杂事 买书 啃书 unity基本demo

    早上九点多去万维对接老板说的产品演示ppt,杨主任不在和办公室另一qishihui下午去7楼会议室。

    回来后,中午研究unity终于做出来简单的通过button按钮基本控制camvas镜头,原来x,y,z并不是控制绝对位置,而是unity已经提供好的每次移动改变距离,所以直接填写1f即可(float),并导出安卓包发给老板看以示学习的初步展示与某种相对作用。

    下午勉强的以万维身份应付讲完ppt内容后,顺路去书店买书,一方面比较在意的《人类群星闪耀时》,另一方面主要买些闲杂书想尽量取代一些打游戏的时间填补些充实感。

    逛了约有两小时吧,不清楚,刚好算上即时贴买了100元整的三本书,万物简史和青春恋爱有问题。

    晚上一直啃书,基本都翻看了半小时大概,小说看得更入味一些,也许可以提高阅读速度吧,知道看困为止约凌晨或是一两点喝了碗热牛奶睡觉。

    关键代码:

    Assets

  • 2021.1.22 墨茶事件 unity的jdk安卓配置

    接近午起,感冒整体好多,鼻子较为通常,无明显头疼耳疼,全天除晚上再次下楼检查丢失的快递无外出。

    小希群里看到墨茶事件,发现后感叹很深,至少我还有最后一两面盾的生存机会和学习过的时光,以后如果再次绝望了,回顾下墨茶,所浪费的今天不正是昨天离去的人所奢望的明天吗。

    下午和晚上继续捉摸unity不吃JDK的问题,始终无法解决,版本不兼容等等,路径找不到,最后通过unityHUB重新安装unity版本时勾选android模组,在首选项勾选使用unity自带的JDK实现了安卓的导出,并成功将b站gal的demo在手机上测试,不过有很多bug,例如不显示文字SL无法关闭等,后联系原作者表示是安卓和PC的存储路径不一样,更改即可,并不愿继续优化该demo。

     

  • unity_galgame_demo及教程说明

    【追风团长】Unity制作简易GalGame剧本系统教程

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

    ADVP1.rar

     

    【教程】火影忍者GalGame游戏制作教程 第一课 基本人物对话与场景的切换

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

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

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

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

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

     

    【自制】unity10天实现小型Galgame逻辑

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

    GalGameDemo_by_sa_源码.rar

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

  • Android SDK 在线更新镜像服务器资源(转载)

    http://tools.android-studio.org/index.php/proxy

    Android SDK 在线更新镜像服务器资源:

    大连东软信息学院镜像服务器地址:

    • http://mirrors.neusoft.edu.cn 端口:80

    北京化工大学镜像服务器地址:

    • IPv4: http://ubuntu.buct.edu.cn/ 端口:80
    • IPv4: http://ubuntu.buct.cn/ 端口:80
    • IPv6: http://ubuntu.buct6.edu.cn/ 端口:80

    上海GDG镜像服务器地址:

    • http://sdk.gdgshanghai.com 端口:8000

    中国科学院开源协会镜像站地址:

    • IPV4/IPV6: http://mirrors.opencas.cn 端口:80
    • IPV4/IPV6: http://mirrors.opencas.org 端口:80
    • IPV4/IPV6: http://mirrors.opencas.ac.cn 端口:80

    腾讯Bugly 镜像:

    • http://android-mirror.bugly.qq.com 端口:8080
    • 腾讯镜像使用方法: http://android-mirror.bugly.qq.com:8080/include/usage.html

    使用方法:

    1. 启动 Android SDK Manager ,打开主界面,依次选择『Tools』、『Options…』,弹出『Android SDK Manager – Settings』窗口;
    2. 在『Android SDK Manager – Settings』窗口中,在『HTTP Proxy Server」和「HTTP Proxy Port』输入框内填入上面镜像服务器地址和端口,并且选中『Force https://… sources to be fetched using http://…』复选框。设置完成后单击『Close』按钮关闭『Android SDK Manager – Settings』窗口返回到主界面;
    3. 依次选择『Packages』、『Reload』。
  • Unity Live2D的接入和使用(转载)

    https://blog.csdn.net/weixin_38813436/article/details/106472110

    预制件原来自动生成的啊。。

     

    下载地址

    Live2D下载地址

    Live2D的使用

    Live2D导入Unity后文件结构如下,并且官方也提供了多个演示场景以供大家学习使用。

    在这里插入图片描述
    基本功能和使用。
    导入前的Live2D文件结构如下:在这里插入图片描述
    分别为表情的Json配置文件,动作的Json配置文件,贴图以及物理Json配置文件等。
    将此导入Unity后Live2D会自动处理配置文件,并在Runtime文件夹下生成Liv2D的预制体,expressionList表情列表和fadeMotionList动作列表,列表的引用关系Live2D已自动处理。
    在这里插入图片描述
    在这里插入图片描述
    Live2D预制体所挂脚本:
    在这里插入图片描述
    可选功能脚本:
    LookController与LookTarget配合使用,控制Live2D的鼠标追踪效果。
    Mouth,EyeBlink控制Live2D自动眨眼功能和嘴巴张闭。
    Expression表情管理。
    Fade 动作淡入淡出管理。
    同时自动眨眼还有鼠标追踪等功能,需要在相应可动部位添加相应功能脚本。
    如自动眨眼:
    在这里插入图片描述
    嘴巴:
    在这里插入图片描述
    鼠标追踪:
    在这里插入图片描述
    这些都是Live2D提供的基本功能,只需要挂载相应脚本便可实现功能。

    动作和表情的播放

    示例脚本:

    using Live2D.Cubism.Core;
    using Live2D.Cubism.Framework;
    using Live2D.Cubism.Framework.Expression;
    using Live2D.Cubism.Framework.Motion;
    using Live2D.Cubism.Framework.Raycasting;
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace Live2D.Cubism.Samples.OriginalWorkflow.Demo
    {
        [RequireComponent(typeof(CubismMotionController))]
        [RequireComponent(typeof(CubismRaycaster))]
        public class CubismSampleController : MonoBehaviour
        {
            /// <summary>
            /// MotionController to be operated.
            /// </summary>
            private CubismMotionController _motionController;
    
            /// <summary>
            /// ExpressionController to be operated.
            /// </summary>
            private CubismExpressionController _expressionController;
    
            /// <summary>
            /// Operation animation clip from the inspector.
            /// </summary>
            [SerializeField]
            private AnimationClip _bodyAnimation;
    
            /// <summary>
            /// Array of motion set in tapbody.
            /// </summary>
            [SerializeField]
            private AnimationClip[] _tapBodyMotions;
    
            /// <summary>
            /// Motion set in roop motion.
            /// </summary>
            private AnimationClip _roopMotion;
    
            /// <summary>
            /// List of Drawables info.
            /// </summary>
            private List<HitDrawableInfomation> _hasHitDrawables;
    
            /// <summary>
            /// Component that performs ray judgment on Drawables of model.
            /// </summary>
            private CubismRaycaster _raycaster;
    
            /// <summary>
            /// Raycast Hit Results.
            /// </summary>
            private CubismRaycastHit[] _raycastResults;
    
            /// <summary>
            /// Enumeration type for hit area discrimination.
            /// </summary>
            private enum HitArea
            {
                Head,
                Body
            }
    
            /// <summary>
            /// Structure that stores Drawable information for which hit area is specified.
            /// </summary>
            private struct HitDrawableInfomation
            {
                /// <summary>
                /// Drawable with component set.
                /// </summary>
                public CubismDrawable drawable;
    
                /// <summary>
                /// HitArea.
                /// </summary>
                public HitArea hitArea;
            }
    
    
            /// <summary>
            /// Load model.
            /// </summary>
            private void Start()
            {
                var model = this.FindCubismModel();
    
                // Get components.
                _motionController = model.GetComponent<CubismMotionController>();
                _expressionController = model.GetComponent<CubismExpressionController>();
                _raycaster = model.GetComponent<CubismRaycaster>();
    
    
                // Set behavior at the end of animation.
                _motionController.AnimationEndHandler = AnimationEnded;
    
    
                // Get up to 4 results of collision detection.
                _raycastResults = new CubismRaycastHit[4];
    
    
                // Cache the drawable in which the component is set.
                {
                    _hasHitDrawables = new List<HitDrawableInfomation>();
    
                    var hitAreas = Enum.GetValues(typeof(HitArea));
                    var drawables = model.Drawables;
    
    
                    for (var i = 0; i < hitAreas.Length; i++)
                    {
                        for (var j = 0; j < drawables.Length; j++)
                        {
                            var cubismHitDrawable = drawables[j].GetComponent<CubismHitDrawable>();
    
                            if (cubismHitDrawable)
                            {
                                if (cubismHitDrawable.Name == hitAreas.GetValue(i).ToString())
                                {
                                    var hitDrawable = new HitDrawableInfomation();
                                    hitDrawable.drawable = drawables[j];
                                    hitDrawable.hitArea = (HitArea)i;
    
                                    _hasHitDrawables.Add(hitDrawable);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
    
    
            /// <summary>
            /// Update.
            /// </summary>
            private void Update()
            {
                // Play if animation is specified.
                SpecifiedAnimationCheck();
    
    
                if(!Input.GetMouseButtonDown(0))
                {
                    return;
                }
    
    
                // Cast ray from pointer position.
                var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                var hitCount = _raycaster.Raycast(ray, _raycastResults);
    
    
                // Motion playback according to the hit location.
                for (var i = 0; i < hitCount; i++)
                {
                    var hitDrawable = _raycastResults[i].Drawable;
    
                    for (var j = 0; j < _hasHitDrawables.Count; j++)
                    {
                        if (hitDrawable == _hasHitDrawables[j].drawable)
                        {
                            var hitArea = _hasHitDrawables[j].hitArea;
    
    
                            // Tap body.
                            if (hitArea == HitArea.Body)
                            {
                                // Decide motion to play at random.
                                var motionIndex = UnityEngine.Random.Range(0, _tapBodyMotions.Length - 1);
    
                                Debug.Log("Tap body : Play : " + _tapBodyMotions[motionIndex].name);
    
                                _motionController.PlayAnimation(_tapBodyMotions[motionIndex], isLoop: false, priority:CubismMotionPriority.PriorityNormal);
                            }
                            // Tap head.
                            else if (hitArea == HitArea.Head)
                            {
                                // Decide expression motion to play at random.
                                var expressionNum = _expressionController.ExpressionsList.CubismExpressionObjects.Length;
                                var expressionIndex = UnityEngine.Random.Range(0, expressionNum - 1);
    
                                _expressionController.CurrentExpressionIndex = expressionIndex;
    
                                Debug.Log("Tap head : Play : " + _expressionController.ExpressionsList.CubismExpressionObjects[expressionIndex].name);
                            }
    
                            break;
                        }
                    }
                }
            }
    
    
            /// <summary>
            /// Check the specified animation and play it.
            /// </summary>
            private void SpecifiedAnimationCheck()
            {
                if(_bodyAnimation != _roopMotion)
                {
                    _roopMotion = _bodyAnimation;
    
                    Debug.Log("Body animation : Play : " + _roopMotion.name);
    
                    _motionController.PlayAnimation(_roopMotion, priority:CubismMotionPriority.PriorityIdle);
                }
            }
    
    
            /// <summary>
            /// Called at the end of the animation.
            /// </summary>
            /// <param name="instanceId"></param>
            private void AnimationEnded(float instanceId)
            {
                // Play roop motion.
                _motionController.PlayAnimation(_roopMotion, priority:CubismMotionPriority.PriorityIdle);
    
                Debug.Log("Body animation : Play : " + _roopMotion.name);
            }
        }
    }
    

    注意,可交互部位要挂载相应功能脚本,点击才会生效。如要点击身体部位,可在预制体的Drawables下将相关区域挂载CubismHitDrawable与CubismRaycastable脚本。如:
    在这里插入图片描述
    如此,射线检测到点击的相应区域,便可播放相应的动作或者表情了。

     

  • Unity开发之如何创建Prefab(预制件)(转载)

    https://jingyan.baidu.com/article/e5c39bf5aa02f639d76033f8.html

     

    发现l2d官方demo的l2d模型model文件内都有prefab文件,初步判断是已经拼好的模型,类如u3d中的moc

     

    在Unity官方文档中在介绍GameObjects时提到一个概念Prefab,翻译成中文就是预制件。

    那什么是Prefab呢?

    在我们制作的场景中,如战斗中的子弹,森林里的树木,此类游戏对象会在同一个场景重复使用。为了方便同时修改这些对象,就可以使用Prefab这些对象,而只需要修改Prefab就可以将修改作用到所有由该Prefab生成的对象上。

    工具/原料

    • Unity3D
    • Macbook

    方法/步骤

    1. 在“Project”界面上,右键点击“Assets”打开右键菜单,依次选择“Create”->“Prefab”,这样创建一个Prefab资源,此处命令为test

      Unity开发之如何创建Prefab(预制件)
    2. 选中场景后,在场景的“Hierachy”界面中打开右键菜单,依次选择“3D Object”->“Cube”

      Unity开发之如何创建Prefab(预制件)
    3. 将Cube对象拖动到第一步中创建的Prefab资源上

      Unity开发之如何创建Prefab(预制件)
    4. 完成第三步后,可以发现Prefab资源的样式发生了变化,这说明该Prefab资源成功创建

      Unity开发之如何创建Prefab(预制件)
    5. 你可以将Prefab资源直接拖动场景中就可以使用该Prefab 了

      Unity开发之如何创建Prefab(预制件)

     

  • Live2D for Unity入门篇 4.x(转载)

    https://zhuanlan.zhihu.com/p/141905772

     

    待尝试

     

    一直都想转型U3D,然后都因为各种原因没有落实。

    这次疫情原因,需要重新找工作,然后有一个机会可以转U3D开发。所以重新拿起来,希望能抓住这个机会,项目是二次元向,所有需要用到Live2D。

    上次自学过一段时间U3D,但是已经比较久远了。久远到这次回来重新使用,发现变化还蛮大的。

    具体的U3D安装啥的,没啥难度,直接官网下载就行了。但是不得不说,现在用的这个Unity Hub真心不太好用,经常出各种小问题,目前的解决方案就是卸载了然后重新安装。(可能是因为不熟悉,后面熟悉了应该会好很多。重心不在这,所以不过多纠结)。

    然后再说到Live2D,这 玩意儿不清楚的可以直接百度,或者谷歌。去Live2D官网查看相关消息。

    www.live2d.com

    我这次用到的是Live2D for Unity 也就是Live2D的Unity版本。现在官网最新的版本已经到了4.0。网上找了一些相关的教程来看,发现基本都是2.0的。有一些流程和4.0差异比较大。

    然后在官网寻找教程,发现还是这个靠谱。

    docs.live2d.com/cubism-

    具体可以查看这个链接。不过有一点,官网的这个翻译,一言难尽。(~ ̄▽ ̄)~

    相比较2.0版本,最新的4.0优化了好多步骤。

    新建一个c#文件,命名为Live2DModel。具体代码如下:

    using System;
    using System.IO;
    using UnityEngine;
    using Live2D.Cubism.Framework.Json;
    public class Live2DModel : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            var path = Application.streamingAssetsPath + "/koharu/koharu.model3.json";
            var model3Json = CubismModel3Json.LoadAtPath(path,BuiltinLoadAssetAtPath);
    
            var model = model3Json.ToModel();
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        public static object BuiltinLoadAssetAtPath(Type assetType,string absolutePath)
        {
            if(assetType == typeof(byte[])){
                return File.ReadAllBytes(absolutePath);
            }else if(assetType == typeof(string)){
                return File.ReadAllText(absolutePath);
            }else if(assetType == typeof(Texture2D)){
                var texture = new Texture2D(1,1);
                texture.LoadImage(File.ReadAllBytes(absolutePath));
    
                return texture;
            }
            return new NotSupportedException();
        }
    }
    

    具体可以查看官方文档。

    然后将文件挂载到一个空的GameObject上面。直接运行之后就会看到模型已经显示在场景上了。

    在这期间遇到一个特别坑的问题。代码编辑器使用的IDE是VSCode,没有代码补全,提示是找打不到对应的.net framework版本。项目默认的版本是V4.1.1。尝试了以下方法:

    1. 从微软官方下载对应的开发者版本,因为系统无法卸载高级版本,但是我们可以安装多版本。(当然也有方法可以卸载,但是容易出现问题,不建议)
    2. 直接修改项目中Assembly- XXX文件 中的TargetFramworkVersion的版本。但是这个版本会自动覆盖,而且手动更改好像也无效。
    3. 百度的各种其他乱七八糟的方法。

    最后实在没办法的情况下,下载了Visual Studio 2017来作为IDE,结果没想到安装好了之后,VSCode也好了。暂时还没有确定问题到底在哪儿。

    自此,Live2D的入门也就完成了。下一步是动作文件的处理。

  • unity3d使用VS2010编写C#代码(转载)

    https://jingyan.baidu.com/article/380abd0a15e7621d90192c3b.html

     

    使用unity3d进行游戏开发时,默认的代码编写工具是MonoDevelop。而如果我们使用的C#语言,也可以使用VS进行代码编写,以适合一些C#老程序员的习惯。

    工具/原料

    • unity3d
    • VS2010

    方法/步骤

    1. 这里我使用VS2010做演示。首先需要安装好unity3d和VS2010,这在网上很容易找到。

    2. 打开unity3d,新建一个项目,然后在Assets中创建一个C#脚本文件。

      unity3d使用VS2010编写C#代码
      unity3d使用VS2010编写C#代码
    3. 双击打开C#脚本文件,默认状态下是使用MonoDevelop打开。

      unity3d使用VS2010编写C#代码
    4. 需要把默认的代码编辑器改为VS2010。选择菜单栏上的Edit选项,在下拉框中点击Preferences选项。

      unity3d使用VS2010编写C#代码
    5. 在Unity Preferences界面,选择第二项External Tools,把External Script Editor选择VS2010(如果安装了VS2010这里就会显示)。

      unity3d使用VS2010编写C#代码
    6. 然后再次打开C#脚本文件,刚打开会有点慢,有进度条。然后就能在VS中编辑Unity3d使用的C#代码。

      unity3d使用VS2010编写C#代码
      unity3d使用VS2010编写C#代码
    7. 7

      修改代码后,保存即可,无需编译生成。在Unity中调试游戏时,会自动编译。当然也可以在VS选择生成,测试有没有编译错误。

      END

    注意事项

    • 使用什么工具编写代码根据自己的习惯而定,不一定要使用VS
  • Unity3D 学习教程 11 c#脚本控制摄像头(转载)

    https://www.cnblogs.com/goodchenqing/p/4206979.html

     

    首先新建一个脚本

    点击创建一个文件夹起名C#

    点击文件夹 创建一个C#脚本

    建好文件后 双击文件

    启动脚本编辑器

    void Start () 是场景运行时加载程序

    void Update ()  是每调用一针执行一次  可以认为是试试执行的程序

    下面编写第一个脚本

    控制摄像机移动

    using UnityEngine;

    using System.Collections;

     

    public class acc : MonoBehaviour

    {

     

    int speed=50;

    void Start ()

    {

    }

    void Update ()

    {

    float x = Input.GetAxis(“Horizontal”) * Time.deltaTime * speed;//左右移动

    float z = Input.GetAxis(“Vertical”) * Time.deltaTime * speed;// 前后移动

    //主摄像机物体    移动

    transform.Translate(x,0,z);

    }

    }

    Input.GetAxis 是输入管理器

    点击edit

    了解下输入管理器

    红色部分是按键信息

    Horizontal是平行移动   按a  d 键和<– –> 方向键就可以平移了

    调用代码

    Input.GetAxis(“Horizontal”)

    Time.deltaTime 是时间间隔

    speed = 50;  是步长

    左右移动的距离

    float x = Input.GetAxis(“Horizontal”) * Time.deltaTime * speed;//左右移动

    float z = Input.GetAxis(“Vertical”) * Time.deltaTime * speed;// 前后移动

     

    //主摄像机物体    移动

    transform.Translate(x,0,z)

     

    最后把脚本绑定在摄像头上

    拖放

     

    unity3d摄像机详解
    正如电影中的镜头用来将故事呈现给观众一样,Unity的相机用来将游戏世界呈现给玩家。你始终至少有一个相机在场景中,你也可以有多个。多相机可以给你一个双人分屏效果或创建高级的自定义效果。你可以让相机动起来,或用物理(组件)控制它们。几乎你能想到的任何事,都可以用相机变成可能,而且为了适合你的游戏风格,你可以用典型的或特殊的相机类型。
    摄像机
    相机是为玩家捕捉和显示世界的一种装置。通过定制和操作相机,可以让你的游戏外观与众不同。在一个场景中你可以有数量不限的相机。它们可以被设置为以任何顺序来渲染,在屏幕上的任何地方来渲染,或仅仅渲染屏幕的一部分。

    属性
    ·Clear Flags 清除标记 决定屏幕的哪部分将被清除。当使用多个相机来描绘不同的游戏景象时,利用它是非常方便的

    ·Background 背景 在镜头中的所有元素描绘完成且没有天空盒的情况下,将选中的颜色应用到剩余的屏幕

    ·Culling Mask 剔除遮罩 包含或忽略相机渲染对象层。在检视视图中为你的对象指派层

    ·Projection 投射 切换摄像机的模拟透视功能

    ·–> Perspective 透视 相机将用完全透视的方式来渲染对象。

    ·–> Orthographic 正交 相机将用没有透视感的方式均匀地渲染对象

    ·Size 大小 当设置了正交时摄像机的视口大小。

    ·Field of view 视野范围 相机的视角宽度,以及纵向的角度尺寸。

    ·Clipping Planes 剪裁平面 从相机到开始渲染和停止渲染之间的距离。

    ·–> Near 近点 开始描绘的相对于相机最近的点。

    ·–> Far 远点 开始描绘的相对于相机最远的点。

    ·归一化视口矩形 用四个数值来表示这个相机的视图将绘制在屏幕的什么地方,使用屏幕坐标系(值0-1)。

    ·–> X 相机视图将进行绘制的水平位置的起点

    ·–> Y 相机视图将进行绘制的垂直位置的起点

    ·–> W (Width) 宽度 相机输出到屏幕上的宽度

    ·–> H (Height) 高度

    ·相机输出到屏幕上的高度

    ·Depth 深度 绘图顺序中的相机位置,具有较大值的相机将被绘制在具有较小值的相机的上面

    ·Rendering Path 渲染路径 该选项定义相机将要使用的渲染方法

    ·–> Use Player Settings      使用播放器设置 该相机将使用任意一个播放器设置中所设置的渲染路径

    ·–> Vertex Lit 顶点光照 本相机对所有对象的渲染会作为顶点光照对象来渲染

    ·–> Forward 快速渲染 所有对象将按每种材质一个通道的方式来渲染,如同在Unity2.x中的标准

    ·–> Deferred Lighting 延迟照明 所有对象将无照明绘制一次,然后所有对象的照明将一起在渲染队列的末尾被渲染

    。
    ·Target Texture 目标纹理 (Unity Pro/Advanced only) 请参考Render Texture,该页包含了相机视图的输出。这个引用属性将禁用相机渲染到屏幕的功能。
    细节

    相机对于将你的游戏显示给玩家是必不可少的。它们可以被定制、被脚本化、或被子类化以实现几乎任何可以想象的效果。对于一个益智游戏,你要保持相机处于静态显示全部视角。对于第一人称射击游戏,你应该将相机作为玩家角色的子对象,并将其放置在与角色的眼睛等高水平上。对于一个赛车游戏,你可能更希望让相机跟随玩家的车辆。

    你可以创建多个相机并且给每一个分配不同的深度。相机是按深度从低到高来绘制的,换言之,一个深度为2的相机将绘制在一个深度为1的相机之上。你可以调整标准视口矩形(参照前面的属性列表)的属性值来改变其大小和其在屏幕上的位置。这样你就可以创建多个小视窗,如导弹控制器,小地图窗口,后视镜等等。

     

  • N种让Unity陷入死循环的方法(转载)

    http://blog.sina.com.cn/s/blog_4a2183a601018fki.html
    用了2年多unity了, 犯过N多白痴错误,比如各种死循环bug….

    最傻逼的 while循环无法满足退出条件

    while(a<b) DoSomething(); 结果写错条件导致a 永远不会大于b,悲剧了….
    最白痴的 for循环也能死
    for(int i=n; i>=0; i-=2)中不幸吧i-=2写成i=2…..
    假死变真死
    协同函数 while(true){} 里忘记写 yield return 1…… 
    函数调用判断条件失误
    某个 插件里偶尔会发生的, Function1调用了Function2, Function2判断条件不满足又调用了Function1……
    递归归归归归归……
    某个同事干的,递归查询路径写入周围连接点的时候忘记检查吧上一级也写入了…..
    我需要那个组件…..
    unity里可以用 RequireComponent 要求这个脚本需要一个组件支援,有个功能分成两个脚本写,鉴于加上这个如果物体上没有这个组件就会自动添加需要的组件,于是我在两个脚本上都加上了RequreireComponent另一个脚本,于是…….