最傻逼的 while循环无法满足退出条件
分类: 技术教程
-
N种让Unity陷入死循环的方法(转载)
http://blog.sina.com.cn/s/blog_4a2183a601018fki.html用了2年多unity了, 犯过N多白痴错误,比如各种死循环bug….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另一个脚本,于是……. -
C# Await(转载)
https://www.cnblogs.com/haibozhu/p/11407647.html
2020.11.18 用于延迟时钟等方面的,存在异步调用注意事项,待继续学习了解
每次提到异步我都选择绕开,感觉深不可测,最近打算看看异步,但又不愿意看书,网上找了几个视频看,发现传智播客的老师讲异步都不是很深入,关键的问题一笔带过,倒是把我弄糊涂了,印象最深刻的是那个老师说的一句话:“在异步函数中,Await之后会自动创建出一个线程”。确实,在控制台程序中是这样,但是在winform中却不都在UI线程中执行,感觉内部隐藏不可告人的秘密,索性自己探索一下。
控制台程序:
static void Main(string[] args) { Console.WriteLine("1.同步ThreaID:" + Thread.CurrentThread.ManagedThreadId); RunTimeAsync(); Console.WriteLine("4.异步执行完毕ThreaID:" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Console.WriteLine("5.同步延迟完毕ThreaID:" + Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); } public async static Task RunTimeAsync() { Console.WriteLine("2.进入异步ThreaID:" + Thread.CurrentThread.ManagedThreadId); await Task.Delay(1000); Console.WriteLine("3.异步执行后ThreaID:" + Thread.CurrentThread.ManagedThreadId); }执行结果:

同样的代码在winform中执行:
winform程序:
private void button1_Click(object sender, EventArgs e) { Console.WriteLine("1.同步ThreaID:" + Thread.CurrentThread.ManagedThreadId); RunTimeAsync(); Console.WriteLine("4.异步执行完毕ThreaID:" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(2000); Console.WriteLine("5.同步延迟完毕ThreaID:" + Thread.CurrentThread.ManagedThreadId); } public async static Task RunTimeAsync() { Console.WriteLine("2.进入异步ThreaID:" + Thread.CurrentThread.ManagedThreadId); await Task.Delay(1000); Console.WriteLine("3.异步执行后ThreaID:" + Thread.CurrentThread.ManagedThreadId); }执行结果:

前后代码执行结果对比后发现,
1.线程数量,winfrom都是在一个线程里执行,控制台程序是两个线程执行,其中异步操作在新的线程里。
2.执行顺序,winform先执行click中同步操作,再执行异步操作,控制台却相反。
所以await这个关键字到底对异步操作动了什么手脚呢?
在查了一些相关资料后有两个词比较高频:SynchronizationContext 和TaskScheduler,执行代码时,Task不会自己执行,而是将执行内容放到SynchronizationContext 和TaskScheduler执行。
其实await Task.Delay(1000)或者await AsyncFun()(异步操作)等价于以下代码:
Task t = AsyncFun();
var currentContext = SynchronizationContext.Current;
if (null == currentContext)
{
t.ContinueWith((te) => { Run(); }, TaskScheduler.Current);
}
else
{
t.ContinueWith((te) => { Run(); }, TaskScheduler.FromCurrentSynchronizationContext())}
如果SynchronizationContext为null就在TaskScheduler中执行,如果不为null则在FromCurrentSynchronizationContext中执行。
先了解一下TaskScheduler——–CSDN中注解是:表示一个处理将任务排队到线程中的低级工作的对象。
看一下TaskScheduler的元数据:

TaskScheduler其实就是将Task放到Threadpool执行,通过入队出队的方式排列执行顺序。
根据等价代码我们要区分一下控制台程序与winfrom程序异步操作的执行方式,
我们执行这条代码:var currentContext = SynchronizationContext.Current;
在控制台程序中currentContext 为null
在winform中currentContext 为System.Windows.Forms.WindowsFormsSynchronizationContext
那么控制台程序是在TaskScheduler.Current所在的线程池执行,我们看到控制台的await 异步操作在其他线程中执行一致。
下面分析一下winform的执行方式:
WindowsFormsSynchronizationContext继承自SynchronizationContext,
https://www.cnblogs.com/lzxianren/p/SynchronizationContext.html 参考了这篇文章
里面有两点:
public virtual void Send(SendOrPostCallback d, Object state)
{
d(state);
}
public virtual void Post(SendOrPostCallback d, Object state)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(d), state);
}
在UI线程执行是,会将执行的任务用Send方法放到消息泵中,当时UI中同步执行的操作执行完毕,再执行详细泵中的数据,这就是为什么UI中只在一个线程中执行,而且总是在最后执行。
总结:用 await 语句等待一个任务完成,当该方法在 await 处暂停时,就可以捕捉上下文(context)。如果当前 SynchronizationContext 不为空,这个上下文就是当前SynchronizationContext;如果当前 SynchronizationContext 为空,则这个上下文为当前askScheduler,该方法会在这个上下文中继续运行。一般来说,运行 UI 线程时采用 UI 上下文,处理 ASP.NET 请求时采用 ASP.NET 请求上下文,其他很多情况下则采用线程池上下文。因此,在上面的代码中,每个同步程序块会试图在原始的上下文中恢复运行。如果在 UI线程中调用 ,这个方法的每个同步程序块都将在此 UI 线程上运行。但是,如果在线程池线程中调用,每个同步程序块将在线程池线程上运行。
控制台程序以及类库是在TaskScheduler中调度执行,UI程序则是在SynchronizationContext调度执行。
参考了:https://blog.csdn.net/wlk1229/article/details/81287374
-
unity 安卓环境配置sdk,jdk安装(转载)
https://blog.csdn.net/weixin_42399500/article/details/84965034
第一.安装JDK
1.安装。

2.环境变量的改变。


(1)新建->变量名”JAVA_HOME”,变量值”C:\Program Files\Java\jdk1.8.0_171″(即JDK的安装路径)
(2)编辑->变量名”Path”,在原变量值的最后面加上“;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin”
(3)新建->变量名“CLASSPATH”,变量值“.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar”


3.判断是否安装成功。
1.win(键盘左下角第二个)+R,打开命令窗口输入CMD,回车

2.输入 java

第二sdk安装。

1.在c盘解压。

2.下载 应用工具。




注意:如果下载不下来,可以用
此时采用有Android SDK在线更新镜像服务器来下载安装:
1、北京化工大学镜像服务器地址:
IPv4: ubuntu.buct.edu.cn/ 端口:80
IPv4: ubuntu.buct.cn/ 端口:80
IPv6: ubuntu.buct6.edu.cn/ 端口:80
2、大连东软信息学院镜像服务器地址:
mirrors.neusoft.edu.cn 端口:80
3、郑州大学开源镜像站:
mirrors.zzu.edu.cn 端口:80
使用方法:
启动 Android SDK Manager ,打开主界面,依次选择『Tools』、『Options…』,弹出『Android SDK Manager – Settings』窗口;在『Android SDK Manager – Settings』窗口中,在『HTTP Proxy Server』和『HTTP Proxy Port』输入框内填入上面镜像服务器地址(不包含http://,如下图)和端口,并且选中『Force https://… sources to be fetched using http://…』复选框。设置完成后单击『Close』按钮关闭『Android SDK Manager – Settings』窗口返回到主界面;
依次选择『Packages』、『Reload』。第三步:发布


2020.11.19 本人尚未实现,unity提示找不到sdk和jdk依旧推荐1.8.0版本,可能与下载的sdk jdk和unity版本匹配有问题,环境变量均已添加和多次检查及多次重启unity
-
2018年Unity结合Android SDK下载安装及配置教程(转载)
https://blog.csdn.net/dxj467822057/article/details/80198165
首先声明: Unity版本2017.1f3
最近试着在Unity中利用网易做AR开发时,发布项目文件需要发布到Android平台,遇到一些问题,看了网上的一些资料,踩了一些坑,现在总结出来,希望有相同的开发者遇到时可以规避。
第一步、安装JDK;
第二步、安装Eclipse;
第三步、下载并安装AndroidSDK;
第四步、在Unity中发布到Android平台。
安装JDK
官网:http://www.Oracle.com/technetwork/Java/javase/downloads/index.html
按照以下步骤操作即可:
(1)点击图中箭头所指的任意一个都可以。

(2)接受

(3)找到适合自己电脑系统的JDK版本,点击下载

(4)自己选择路径安装完,注:不可以保存在中文路径下。
(5)变量环境的设置:我的电脑/计算机——属性——高级系统设置——环境变量。
①、新建一个系统环境变量,变量名为JAVA_HOME,变量值为JDK的安装路径

②、在系统变量中找到Path,将;%JAVA_HOME%\bin; %JAVA_HOME%\jre\bin添加到变量值后面
注:在变量的最末尾添加时,需要加上分号;
③、检测是否配置成功。打开命令行窗口,输入javac -version。安装成功则看到oracle JDK版本号,如下图所示:

安装Eclipse
官网:http://www.eclipse.org/downloads/
1、下载Eclipse,选择EclipseIDE for Java EE Developers,根据自己的系统选择32位或者64位的安装包,
2、将下载好的安装包解压缩至自己想要的位置,得到如图效果:

3、双击eclipse/eclipse.exe。自己选择工作空间存放位置,出现以下图标则安装成功,若无请检查步骤一JDK是否正确安装和配置。


下载并安装Android SDK
官网(可翻墙选择):http://developer.android.com/sdk/index.html
不可翻墙选择:http://www.androiddevtools.cn/
或者360安全卫士—360软件管家—编程开发—搜索即可。
(下面以第二种方法为例进行下载)
1、下载Android SDK Tools
先找到SDK Tools,下载最新的版本即可。选择zip的,解压缩至目标路径位置即可


2、双击“SDK Manager”,启动SDK Manager
①、Tools的勾选图示选项下载即可。

②、API的任意选择一个,考虑向下兼容原则,可以下载最新的API。
③、Extras的全选

注:无法下载的会出现以下提示

此时采用有Android SDK在线更新镜像服务器来下载安装:
1、北京化工大学镜像服务器地址:
IPv4: ubuntu.buct.edu.cn/ 端口:80
IPv4: ubuntu.buct.cn/ 端口:80
IPv6: ubuntu.buct6.edu.cn/ 端口:80
2、大连东软信息学院镜像服务器地址:
mirrors.neusoft.edu.cn 端口:80
3、郑州大学开源镜像站:
mirrors.zzu.edu.cn 端口:80
使用方法:
启动 Android SDK Manager ,打开主界面,依次选择『Tools』、『Options…』,弹出『Android SDK Manager – Settings』窗口;
在『Android SDK Manager – Settings』窗口中,在『HTTP Proxy Server』和『HTTP Proxy Port』输入框内填入上面镜像服务器地址(不包含http://,如下图)和端口,并且选中『Force https://… sources to be fetched using http://…』复选框。设置完成后单击『Close』按钮关闭『Android SDK Manager – Settings』窗口返回到主界面;
依次选择『Packages』、『Reload』。

3、设置环境变量
①、新建一个系统环境变量,变量名为ANDROID_SDK_HOME,变量值为你的SDK安装路径

②把%ANDROID_SDK_HOME%\platform-tools;%ANDROID_SDK_HOME%\tools添加到Path环境变量中。
③、检测是否配置成功。打开命令行窗口,输入adb。出现如下图所示内容则配置成功:

在Unity中发布到Android平台
①、在发布界面需要将Android-Support-for-Editor点击下载,然后出现以下界面:

②、在Unity中配置好SDK和JDK的安装路径。
Edit—Preferences—External Tools—配置相关路径

③、File—Build Settings—Player Settings

其中步骤3参数介绍:
Company Name(公司名字)
Product Name(产品名字)
Default Icon(apk 图标):可选可不选注:此时可能会出现以下错误

修改方法:将原来的默认值进行修改即可。
设置Build Indentifier属性的值为”com.aaa.bbb”格式。
操作如下:Edit—Project Settings—Player—修改属性值

至此,重新发布即可。
-
Java JDK的下载与安装(转载)
https://www.cnblogs.com/wcrBlog/p/12273577.html
一、前言
JDK全称Java Development ToolKit,是Java语言开发工具包。JDK是整个JAVA的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)
二、下载
首先去官网下载JDK:点我进官网,选择对应的版本,以下以jdk-13.0.0.2-win64版本为例


三、安装JDK
双击安装包,一直下一步即可,安装完成之后需要配置环境变量:
(1)右键“我的电脑”—>“属性”—>“高级系统设置”,点击环境变量,然后开始环境变量的配置。

(2)点击 系统变量 下面的新建按钮,变量名JAVA_HOME(代表你的JDK安装路径),值对应的是你的JDK的安装路径。

(3)选择名为Path的系统变量,点击编辑,在变量值末尾加上 ;%JAVA_HOME%bin;

四、验证
检验是否配置成功:WINDOWS+R键,输入:cmd;进入命令行界面输入:java -version,如果还是提示’java’不是内部命令的话可以重启电脑试试。
-
C#嵌套类的使用方法及特性(转载)
https://blog.csdn.net/luqizheng/article/details/1965220
嵌套类(Nested Class)是在类中定义的类。以下把拥有内嵌类的类称为外部类。根据《深入理解嵌套类和内部类》嵌套类分为静态嵌套类和非静态嵌套类,其中非静态嵌套类页被称为内部类。 嵌套类在UML中是composite的另外一种代码表示形式,表示耦合度更高,并且与外部类更加紧密。
一般类的 访问修饰符可以定义为默认的internal 或者public,而内嵌类就有比较多的选择,可以是为protected、internal、public以及默认的private。
内嵌类与外部类的访问限制
嵌套类可以访问外部类的方法、属性、字段而不管访问修饰符的限制。如:
public class A
{
private static int _AInt;
private int _instanceInt;
private static void AMethod()
{
Console.WriteLine(_AInt);
}
public void SayIt()
{
NestedA.Method( this );
}
/* 嵌套类 定义 */
private class NestedA
{
public static void Method(A a)
{
// 静态成员
_AInt = 100 ;
AMethod();
//实例 成员
a._instanceInt = 10 ;
a.SayIt();
}
}
}但是外部类只能够访问修饰符为public、internal嵌套类的字段、方法、属性。示例如下: public class A
{
public static void AMethod()
{
// 成功
NestedA.StaticMethod();
// 编译报错
NestedA._Int = 100 ;
NestedA ins = new NestedA();
// 成功
ins.Method();
// 编译报错
ins._instanceInt = 100 ;
}
/* 嵌套类 定义 */
private class NestedA
{
private static int _Int;
private int _instanceInt;
public static void StaticMethod() { }
public void Method(){}
}
}嵌套类访问外部类实例的方法、字段、属性时候。一般在采取构造函数输入外部类。如下: public class A
{
private int _a;
/* 嵌套类 定义 */
private class NestedA
{
public NestedA(A a)
{
a._a = 9 ;
}
}
}继承
继承类,也就是继承类外部类的类,只能使用父类中嵌套类的public或者internal(同一个程序集合)方法。但是继承类可以再定义一个内嵌类并从继承父类中嵌套类。如:public class A
{
/* 嵌套类 定义 */
protected class Nested
{
protected virtual void BaseNested_Method(){}
}
}public class C : A
{
/* 内嵌类 定义 */
protected class C_Nested:Nested
{
protected override void BaseNested_Method()
{
// 重写部分
}
}
}因为C中A中继承,因此C_Nested可以继承Nested类,从而获取重写父嵌套类的机会。但是Nested必须是可继承类及可访问的(非private 、sealed、static)。
嵌套类可以随意外部类的任何数据属性,而外部类访问嵌套类就只能遵守访问修饰符。从这个角度看,嵌套类是外部类的补充,通过嵌套类可以获取更好的封装性,增加外部类的可维护性和可读性。
从程序结构看,嵌套类在逻辑上更加接近使用类。可以更有效地表示类与类之间的紧密程度。为类管理提供除命名空间外的另一种方法。
懒加载
嵌套类的静态构造函数不会随着外部类的触发而初始化。因此可以有效地避免创建时候初始化时间,当需要使用内嵌类的时候,嵌套类才开始初始化才开始初始化。public class Outside
{
static Outside()
{
Console.WriteLine( ” Outside Inilizlized ” );
}
public void SayIt()
{
Nested.Run();
}
private class Nested
{
static Nested()
{
Console.WriteLine( ” Nested initilized ” );
}public static void Run()
{
Console.WriteLine( ” Nested Run ” );
}
}
}执行结果 Outside o = new Outside(); // 打印”Outside Inilizlized”
Console.ReadLine();
o.SayIt(); // 首先打印”Nested initilized” 再打印 “Nested Run”
Console.ReadLine();一般应用这个特性会在一些C#单例模式中找到,而这种模式可以被称为Fully lazy singleton模式。下面是简单的演示代码(Singleton模式可以在这里有更加详细的解释):public class Singleton
{
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
private class Nested
{
public readonly static Singleton instance = new Singleton();
}
}反射
反射内嵌类需要使用”+”而不是我们常使用的”.” 。如A类在Assembly名称为InsideClass中。namespace InsideClass
{
public class A
{
public class Nested
{
protected void BaseNested_Method()
{
}
}
}
}执行 // 成功
object o1 = System.Activator.CreateInstance( ” InsideClass ” , ” InsideClass.A+Nested ” );
// 失败 抛出System.TypeLoadException 异常
object o2 = System.Activator.CreateInstance( ” InsideClass ” , ” InsideClass.A.Nested ” );
