2015-06-03 11:27:35 skylin19840101 阅读数 1787
  • Unity3D的UI系统(UGUI)初级入门

    本课程主要介绍Unity3d的UI系统(UGUI),先对UGUI做一个总体概述,之后对每个UI控件逐一进行详细讲述,内容包括控件的作用、设置方法、使用场景及属性细节,帮助大家熟练使用UGUI设计游戏的交互界面。

    1032 人正在学习 去看看 伍晓波

开发手机游戏都知道,你要接入各种平台的SDK。那就需要Unity3d与iOS中Objective-C的函数有交互,所以你就需要用到如下内容:


一、Unity3d To iOS:


1、创建一个C#文件 SdkToIOS.cs 这是调用iOS函数的接口:

?
    

    2、编写与接口对应的Objective-c函数:

?




         

           


            


           


      值得一提的是在上面的代码中特意写了一个返回字符串的例子,因为你要获取用户ID 、昵称什么的。对应在cs文件中导入函数如下:

?

      


     这里的const char* 会被C#自动转换成string因为在m文件中使用了内存申请,该段内存自然是处在堆内存中,这样转成string符合c#的内存管理机制,我们不用担心它的释放问题。


3、在你的工程目录中找个地方保存iOS的文件

打包出XCode工程后导入进去,加入你的SDK就可以了。

有一点需要说明,如果存放目录为\Assets\Plugins\iOS,那么Unity3d会自动将该目录下的所有文件(暂不支持子文件夹)当做插件文件打包到Xcode工程下的Libraries目录下,这样你就不需要在手动添加了,否则会报错重复声明什么的。

这种文件各个平台会有多个,可以使用同一头文件且定义的C函数名也都相同,这样更有利于多版本管理。


二、iOS To Unity3d

这个在上面的 MyIOSSdk.m 文件中已经有剧透了,就是利用unity3d 的UnitySendMessage函数,其中参数1是场景中接受消息的对象,参数2是要执行的函数名,参数3为传入参数,只要按照如下步骤就可以实现这个机制:

1、在场景中创建一个对象用于接受iOS消息,或者用现有的也可以;

2、为SDK消息写一个脚本,里面包含各种消息函数;

3、将脚本挂到之前创建的对象上完事;

需要注意:这个对象在场景切换时候要始终存在,或者你在每个场景中都加个这玩意也可以,总之只要能收到消息就行了;

2012-08-13 23:48:27 shenjichao2008 阅读数 105
  • Unity3D的UI系统(UGUI)初级入门

    本课程主要介绍Unity3d的UI系统(UGUI),先对UGUI做一个总体概述,之后对每个UI控件逐一进行详细讲述,内容包括控件的作用、设置方法、使用场景及属性细节,帮助大家熟练使用UGUI设计游戏的交互界面。

    1032 人正在学习 去看看 伍晓波

由于项目需要,要求用unity来展示三维场景,并在三维中能够方便的查询数据库等。一开始尝试在unity中直接连接数据库,当时连的xml,然而每次发布成网页后都会出现路径找不到等问题,所以迫不得已采用了unity向网页传送数据,网页中处理数据(查询数据库),然后将处理过的数据再反传送给unity,最终在unity中将其展示(在网页中展示更为灵活) <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

原理很简单:

1unity向网页发送数据的函数:Application.ExternalCall("SayHello",gameObject.name),这个函数将调用网页中的SayHello函数,gameObject.name为传递的参数。

2、网页向unity发送数据的函数:网页中用GetUnity().SendMessage(message, "AcceptName", buildingname)函数来调用unity中的函数,此函数的参数messageunity中的物体,AcceptName为物体上的函数,buildingname为传递的参数。

网页中的函数如下:

 1 function SayHello(message){//此函数来接收unity中发送出来的message值,并将处理后的数据再发送回unity
 2       jQuery.post('../Unity/javascript/DBhelper.ashx', {id:message}, function(data)
 3         {
 4             var msg=JSON.parse(data);//
json数据解析
 5              var buildingname = msg[0].Building_name;
 6             var buildingcategory=msg[0].Building_category;
 7             var buildingpic = msg[0].Building_pic;
 8           GetUnity().SendMessage(message, "AcceptName", buildingname);//
unity中的message物体上的MyFunction函数发送buildingname
 9            GetUnity().SendMessage(message, "AcceptCategory", buildingcategory);
10
11            GetUnity().SendMessage(message, "AcceptImg", buildingpic);
12         });   
13 }

此函数将unity中发送的数据message传到DBhelper.ashx中,在DBhelper.ashx中将传递过来的数据进行查询等操作,然后再用GetUnity().SendMessage(message, "AcceptName", buildingname)将处理好的数据buildingname传给unity中的AcceptName函数。

以下是unity中的脚本,可以实现中文,关于中文的实现由于文章有限,在此不再说明,只说明怎样接收网页中的数据。

 1 var chineseSkin : GUISkin;//在此可以选择字体,并设置为中文。建议编辑器设为uft-8
 2
 3 var buildingname:String;//
用来接收从网页中传递过来的buildingname
 4 var buildingcategory:String;//用来接收从网页中传递过来的buildingcategory
 5
 6 var buildingpic:Texture2D;//
用来接收从网页中传递过来的buildingpic
 7 var windowRect0 = Rect (20, 20, 250, 200);
 8 var enable:boolean;
 9 function Awake(){
10 enable = false ;
11 }

//鼠标按下去时触发的事件
12 function OnMouseDown () {
13 Application.ExternalCall("SayHello",gameObject.name);//
向网页中的SayHello函数发送gameObject.name数据
14 enable = true;
15 }
16 function AcceptName(bdname){//
用于接收网页中发送回来的数据
17 buildingname=bdname;
18 }
19 function AcceptCategory(buildingType){//
用于接收网页中发送回来的数据
20 buildingcategory=buildingType;
21 }
22
23 function AcceptImg(img){

//读取文件夹下的图片文件
24 var www :WWW = new WWW("http://localhost:1166/Unity/images/"+img+"");
25 yield www;

//buildingpic设置纹理
26 buildingpic=www.texture;
27 }

//绘制GUI元素时触发的事件
28 function OnGUI(){
29 GUI.skin=chineseSkin;
30 if(enable)
31 {

//绘制一个窗体,记住第三个参数是方法名字
32 windowRect0 = GUI.Window (0, windowRect0, DoMyWindow, "属性");
33 }
34 }

//绘制一个窗体,windID是不可缺少的元素,指向窗体的索引值
35 function DoMyWindow (windowID : int) {
36 GUI.Label(Rect(10,50,80,30),"
建筑物名字");
37 GUI.TextField(Rect(100,50,100,30),buildingname);
38 GUI.Label(Rect(10,100,80,30),"
建筑物类型");
39 GUI.TextField(Rect(100,100,100,30),buildingcategory);
40
41 GUI.DrawTexture(Rect(10,150,200,50),buildingpic,ScaleMode.ScaleToFit,true,0);
42 if(GUI.Button(Rect(190,20,50,30),"
退出")){
43 enable = false;
44 }
45 GUI.DragWindow (Rect (0,0,10000,10000));
46 }

//鼠标在上面时触发
47 function OnMouseOver(){
48     transform.Rotate(0,Time.deltaTime*100,0,Space.World);
49 }

//鼠标进入时触发
50 function OnMouseEnter(){
51     renderer.material.color = Color.blue;
52 }

//鼠标离开时触发
53 function OnMouseExit(){
54     renderer.material.color = Color.yellow;   
55 }

这是unity中的脚本,此脚本实现点击物体,弹出物体的属性。
2015-09-18 23:53:15 chencglt 阅读数 2997
  • Unity3D的UI系统(UGUI)初级入门

    本课程主要介绍Unity3d的UI系统(UGUI),先对UGUI做一个总体概述,之后对每个UI控件逐一进行详细讲述,内容包括控件的作用、设置方法、使用场景及属性细节,帮助大家熟练使用UGUI设计游戏的交互界面。

    1032 人正在学习 去看看 伍晓波
2018-08-30 15:54:50 IT666DHW 阅读数 432
  • Unity3D的UI系统(UGUI)初级入门

    本课程主要介绍Unity3d的UI系统(UGUI),先对UGUI做一个总体概述,之后对每个UI控件逐一进行详细讲述,内容包括控件的作用、设置方法、使用场景及属性细节,帮助大家熟练使用UGUI设计游戏的交互界面。

    1032 人正在学习 去看看 伍晓波

通用的流程

https://blog.csdn.net/zhangdi2017/article/details/65629589


应用场景

Unity游戏中一些功能需要安卓系统的支持,如搜索wifi等。而且想接入SDK时,很多都是针对安卓的SDK,很少有针对Unity的,所以必须要学习Unity和Android的互调。

网上能搜到很多相关的内容,但大多由于年代久远,Unity和Android Studio版本更新等问题,导致各种无尽的报错让人崩溃,所以还是要记录一下。

环境

  • Unity5.6或2017.3.0f3 + JDK1.8.0_131 + Android Studio3.0.1 + gradle-4.1-all + Visual Studio2017
  • Unity2017高版本取消了Internal的打包方式。
  • VS还好,另外几个要小心各种版本感人莫名其妙的Bug兼容问题!!!!!
  • JDK可以是7或8,一定不能是9!
  • Android Studio上次手贱点了升级,升到v3.1后打包出来目录结构有变动,找不到jar包的位置。且打出的aar包在Unity中调用显示找不到目标方法。

Unity与Android的交互有两种思路

http://www.sikiedu.com/course/137/task/4910/show#
一、Unity做好项目之后导出为Android Studio项目,导入到Android Studio中进行之后的功能开发。最后由Android Studio打包APK。即Unity辅助Android开发(Android开发为主),对Android技能要求较高。
二、Android Sutido做好项目导出jar或aar包,导入到Unity中作为Unity的插件使用,最后由Unity打包APK。即Android辅助Unity开发(Unity开发为主),对Unity技能要求较高。

Unity打包APK时,调用安卓SDK,把所有游戏内容整合打包出的APK中只有一个MainActivity。

一、导出Jar包 + 扩展MainActivity + Java主导

Unity调安卓

复杂度 4.5★    通用度 4.5★    注:官方已经不再推荐这种方法。
http://www.sikiedu.com/course/137/task/4911/show#
1、打开Android Studio新建一个项目,新建一个模块(Module),取名UnityAndroidLibrary。注意选择最小SDK16,因为Unity最小支持的是16。
2、在该模块(ProjectName/UnityAndroidLibrary/src/main/java/packageName/)下新建一个Empty Activity。创建时勾上Launcher Activity。
3、删除跟该界面一同生成的activity_main.xml布局文件(因为之后布局归Unity管理),同时删除该模块MainActivity中onCreate()里调用setContentView()方法。
4、进入Unity的安装目录(如D:\Unity 5.4.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes下)复制classes.jar文件,粘贴到该模块UnityAndroidLibrary/libs目录下。右键该jar选择Add as Library,选Add to Module UnityAndroidLibrary。
5、打开UnityAndroidLibrary模块的AndroidManifest.xml清单文件,该文件会覆盖掉Unity的一些设置,修改如下。(从默认的app模块中的清单文件拷贝过来,把报错的地方去掉即可。记得加后面的meta-data节点)

复制代码

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="guxin.demo.unityandroidlibrary">

    <application
        android:allowBackup="true"
        android:label="UnityAndroidTest"
        android:supportsRtl="true">
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
                <meta-data android:name="unityplayer.UnityActivity" android:value="true"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

复制代码

6、回到模块的MainActivity,修改该类继承自UnityPlayerActivity。在该类中添加自定义的方法,用于给Unity调用。如:

public int add(int a, int b){
    return a + b;
}

7、在AS中Project目录选中unityandroidlibrary,在Build菜单下选Make Module ‘unityandroidlibrary’单独编译这个模块。
8、在unityandroidlibrary/build/intermediates/bundles/debug目录右键Show in Explorer。删除debug/libs/classes.jar(等同于刚从Unity那边拷过来的内容),把debug/classes.jar拖到debug/libs中(这个是包含了刚新增的扩展方法的)。把libs和res这两个文件夹备份(如复制到桌面)。 

 

9、在unityandroidlibrary/build/intermediates/manifests/full/debug/AndroidManifest.xml右键Show in Explorer,也把这个清单文件复制出来(如复制到桌面)。打开在桌面的副本,修改package包名为在Unity中想要的包名,如包名最后一段改为unityandroidtest(注意包名要全部小写)。

10、打开Unity,创建一个工程UnityAndroidTest,Build Settings切换为安卓平台,Player Settings中修改包名,包名同上一步的一致(先调平台再调包名)。在Assets下新建文件夹Plugins/Android(名字固定的,小心别漏了s),将上两步得到的三个文件拖到该文件夹中。

11、新建一个C#脚本,VS打开编辑如下。把该脚本挂到任一场景中的游戏对象上(如Main Camera)。

复制代码

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

public class Test : MonoBehaviour
{
    public Text text; // 用于展示调用结果

    void Start ()
    {
        // 获得位于com.unity3d.player包下的UnityPlayer类,固定写法。
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");   // 参数是包名+类名
        // 获得jc所代表的类里的currentActivity对象,固定写法。这是Unity提供的classes.jar中的功能,可通过currentActivity获取到安卓端代表MainActivty的对象。
        AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        // 调用MainActivty中的自定义方法。
        text.text = jo.Call<int>("add", 1, 2).ToString();
    }

}

复制代码

12、最后一步,连上真机并打开USB调试,Build & Run,路径选择桌面。此时会把APK输出到桌面并安装到真机上运行,即可看到调用结果。下图是我用AS的安卓模拟器(AVD)运行的效果。注意了,要打包发布出来用,直接在Unity编辑器点运行会报错,但打包出来安卓机运行没有问题的。

安卓调Unity

继续上面的工程。

1、在Unity刚才的脚本中,添加一个方法,给安卓调用。

// 交由安卓调Unity。
public void ChangeColor()
{
    text.color = Color.red;
}

2、在安卓端unityandroidlibrary模块的MainActivity类中,修改add()方法。该方法由Unity调用,方法中再由安卓调Unity中的方法,从而实现两者的互调。

复制代码

// Unity调安卓
public int add(int a, int b){
    // 安卓调Unity
    UnityPlayer.UnitySendMessage("Main Camera", "ChangeColor", ""); // 参数:GameObject名 + 方法名 + 参数
    return a + b;
}

复制代码

3、重新把该模块编译。build菜单下选Make Module 'unityandroidlibrary'。同样是在unityandroidlibrary/build/intermediates/bundles/debug目录右键Show in Explorer,拖拽debug/classes.jar到libs中替换掉libs/classes.jar。把libs和res文件夹拷贝到桌面。然后放到Unity中替换掉之前Assets/Plugins/Android目录下的libs和res文件夹。(AndroidManifest.xml可以不用替换)

4、Build & Run 。效果如下。可以看到Text文本颜色变红色了。

 

关于APP在手机桌面上显示的软件名称

当Assets/Plugins/Android/AndroidManifest.xml中的android:label节点指定的软件名,与Unity的Player Settings中Product Name指定的软件名不一致时,最终打出的APK包以前者为准!如下图。

如果上面两者不一致,以安卓清单中的软件名为准。

 

二、导出aar包 + 扩展MainActivity + Java主导

复杂度 4★    通用度 4.5★    注:官方推荐

http://www.sikiedu.com/course/137/task/4915/show#

1、接着上面的项目继续。跟前面导出Jar包的区别是,导出Jar包时(已放到Unity中Assets/Plugins/Android/libs/classes.jar),res文件夹不能跟jar打包到一起,所以Unity2017推荐我们导出aar包(其实解压后就是jar + res)。

2、为演示aar包中包含了资源,在unityandroidlibrary模块的清单文件中加上icon(从另一个app模块的复制),把相应的res/mipmap也复制过来。Build菜单选择‘Build Module unityandroidlibrary’。

3、编译完成后,这次不需要再像上面导出jar那样去找res和libs文件夹,直接找到unityandroidlibrary/build/outputs/aar文件夹,里面就是导出的aar包。把这个aar包和清单文件(还是在unityandroidlibrary/build/intermediates/manifests/full/debug/AndroidManifest.xml)一并拷贝到桌面。

4、打开桌面的清单文件,修改为想要的包名。例如最后一段改为unityandroidtest(全小写,跟Unity中的保持一致)。

5、打开桌面的aar包(zip压缩工具可查看),注意,把包里根目录的classes.jar移动到libs里覆盖里面较大的classes.jar。(复制粘贴,然后删掉libs外面的)

6、观察aar包内容可知,相比导出jar包的方式(只有libs、res、清单xml)多了aidl、jni(提供安卓的高级功能)和R文件、assets(资源文件),这也是Unity推荐使用导出aar替代导出jar的原因之一。

7、把桌面的清单xml文件剪切到Unity的Assets/Plugins/Android/里,这份xml是指导Unity打包APK的总清单,它的包名需要与Unity里写的一致,相对aar包来说是外部的清单。

8、打开桌面aar包里的xml清单文件,删除android:icon和android:label这两行并保存。因为这个xml清单是该模块自己的,为了防止跟aar包外的总清单冲突。

9、最后,再把改好的aar包导入Unity的Assets/Plugins/Android中,项目结构如下。可以看到Unity把aar包识别成了一个插件。

10、启动安卓模拟器,Unity执行Build & Run后即可看到效果。与导出jar包的运行结果一致。

注意:可能会出现Unity能导出APK,但是不能安装到模拟器上的,Unity报错如下。

 直接把APK拖到模拟器中安装,模拟器报错如下。

原因是模拟器上面有过该软件的早期版本,要先卸载了才能再装新版本上去。

 

关于I/Unity: AndroidJavaException: java.lang.NoSuchMethodError: no non-static method with name='add' signature='(II)I' in class Ljava.lang.Object;

复制代码

03-30 02:08:29.073 3957-3972/guxin.demo.unityandroidtest I/Unity: AndroidJavaException: java.lang.NoSuchMethodError: no non-static method with name='add' signature='(II)I' in class Ljava.lang.Object;
    java.lang.NoSuchMethodError: no non-static method with name='add' signature='(II)I' in class Ljava.lang.Object;
        at com.unity3d.player.ReflectionHelper.getMethodID(Unknown Source)
        at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
        at com.unity3d.player.UnityPlayer.c(Unknown Source)
        at com.unity3d.player.UnityPlayer$c$1.handleMessage(Unknown Source)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:154)
        at com.unity3d.player.UnityPlayer$c.run(Unknown Source)
      at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in <filename unknown>:0 
      at UnityEngine.AndroidJNISafe.CallStaticObjectMethod (IntPtr clazz, IntPtr methodID, UnityEngine.jvalue[] args) [0x00000] in <filename unknown>:0 
      at UnityEngine.AndroidReflection.GetMethodMember (IntPtr jclass, System.String methodName, System.String signature, Boolean isStati

复制代码

升级到Android Studio3.1后会出现这个问题,打包出来aar,在Unity中调用显示找不到add()方法!重装Android Studio3.0.1版本。

如果还有该报错,重新新建一个工程,或改用Internal来取代Gradle打包。(高版本Unity2017将取消Internal打包方式)

http://www.sikiedu.com/course/137/thread/1372

三、互调模式之提供Java扩展类

提供额外的类 + Java主导       复杂度 3★    通用度 3.5★

适用场景:在安卓中用Java执行一些操作,且不需要资源(图片等)的情况。可以把Java代码封装成jar后导入Unity中供Unity调用。由于在安卓端编写代码,可以使用安卓的各种高级语法(监听器等)。但由于Test类不能用安卓上下文Context对象,能力有限,所以通用性不高(想传入安卓上下文对象需要额外的操作)。跟上一种方法相比,不是扩展MainActivity,而是另写到一个类中(也因此失去了上下文)。

 

1、打开AS新建一个工程叫SimpleClass,新建一个Module(选Android Library)取名SimpleLibrary。把Unity的classes.jar包导入到该模块中(跟上面一样,这是让安卓能调用Unity的标准操作,即若只想Unity调安卓可以不导入该classes.jar)。

2、新建一个Test类。在该扩展类中编写跟Unity交互的方法。

public class Test {
    public int add(int a, int b){
        UnityPlayer.UnitySendMessage("Main Camera", "ChangeColor", "");
        return a + b;
    }
}

3、Build该模块后,切到Project视图,把simplelibrary/build/intermediates/bundles/debug/classes.jar文件拖到Unity中Asset/Plugins/Android目录下。

4、复制到Unity后,可以给改jar包改名,如改为test.jar。

5、Unity中调用该方法。非静态方法由类的对象来调用。

复制代码

void Start ()
{
    // 获得安卓中test.jar中的Test类对象
    AndroidJavaObject jo = new AndroidJavaObject("me.guxin.simplelibrary.Test"); // 参数:包名,调用空参构造函数
    // 调用类中的自定义方法。
    text.text = jo.Call<int>("add", 1, 2).ToString();

    /* 如果的静态方法
    // 获得安卓中test.jar中的Test类
    AndroidJavaClass jc = new AndroidJavaClass("me.guxin.simplelibrary.Test");
    // 调用静态方法
    text.text = jc.CallStatic<int>("add", 1, 2).ToString();
    */
}

复制代码

6、打包APK后丢到安卓模拟器中运行,即可看到运算结果。


四、互调模式之C#主导式调用

特点:Unity中设置了安卓SDK路径后,可以直接调用安卓SDK中的原生方法,不用从AS中导出插件再导入Unity中。但C#中用反射的写法不能使用Java的一些高级语法。

对于不熟悉安卓开发的同学,可以打开Android Studio新建一个空工程,查看安卓Log()方法的签名,再在Unity中照着安卓的结构写C#代码调用安卓SDK原生方法。

手动打印的安卓错误日志,可以在AS的Log Cat中看到输出。

void Start ()
{
    AndroidJavaClass jc = new AndroidJavaClass("android.util.Log"); // 安卓SDK中的包名
    text.text = jc.CallStatic<int>("e", "UnityAndroidTest", "ErrorTest").ToString(); // 相当于在安卓中写 Log.e("UnityAndroidTest", "ErrorTest");
}

五、各种模式的适用情况

(图来源 http://www.sikiedu.com/course/137/task/4918/show)

Unity中接安卓SDK通常使用的组合:导出aar + 拓展MainActivity + Java主导 。因为第三方SDK通常是争对安卓平台做的。

简单功能可用组合: Class拓展 + C#主导 。适用于简单功能,如调用安卓土司Toast。好处是不用在AS导出项目给Unity当插件使用。


 

参考:

 

2017-03-06 15:35:33 linshuhe1 阅读数 3316
  • Unity3D的UI系统(UGUI)初级入门

    本课程主要介绍Unity3d的UI系统(UGUI),先对UGUI做一个总体概述,之后对每个UI控件逐一进行详细讲述,内容包括控件的作用、设置方法、使用场景及属性细节,帮助大家熟练使用UGUI设计游戏的交互界面。

    1032 人正在学习 去看看 伍晓波

前言:

在我们进行游戏战斗场景开发时,常常为了加强临场感,会在有爆炸或者撞击的时候加入震屏的效果,原理其实很简单,就是对场景主相机进行坐标和角度的变化。


设计

在开始进行代码实操之前,我们先考虑一下大致的思路,主要操作的参数有震动的幅度(Transform的各项参数,通常只改变localPosition和localRotation,必要的时候也可以操作localScale),还有震动的时间,假设无需规则震动,可以考虑通过在振幅范围内取随机数的方法来实现。


实现:

1.创建类,带参数构造方法:

    /// <summary>
    /// 创建振动器
    /// </summary>
    /// <param name="timer">震动时间</param>
    /// <param name="force">震动幅度</param>
    /// <param name="delay">延迟多久震动</param>
    public CameraShaker(float timer, float force,float delay = 0){
       Timer = timer;
       Force = force;
       delayTime = delay;
       Reset();
    }

Rest()方法是用来恢复一些状态和数据信息,以便于通过CameraShaker类创建单个振动器可以反复使用。

2.获得相机的起始位置,方便震动结束之后恢复相机状态:

    m_initialPosition = Camera.main.transform.position;
    m_initialRotation = Camera.main.transform.localRotation;

3.相机震动操作:

这里我直接通过while循环来实现了,当然在MonoBehavior中也可以在Update方法中实现这样的操作,这里为了封装,所以抽离了一些MonoBehavior的特性。

    while (duration > 0)
    {
        Transform objectToMove = Camera.main.transform;
        Vector3 newOffset = new Vector3(UnityEngine.Random.Range(-Force, Force),UnityEngine.Random.Range(-Force, Force),0);
        float newRotationOffset = UnityEngine.Random.Range(-RotationAngle, RotationAngle);
        objectToMove.position = objectToMove.position - m_oldOffset + newOffset;
        objectToMove.Rotate(0, 0, -m_oldRotationOffset);
        objectToMove.Rotate(0, 0, newRotationOffset);
        m_oldOffset = newOffset;
        m_oldRotationOffset = newRotationOffset;
        duration -= Time.deltaTime;
    }

duration为震动时长,而Force为震动的幅度。

4.震动结束后恢复相机参数:

    Camera.main.transform.position = m_initialPosition;
    Camera.main.transform.localRotation = m_initialRotation;
没有更多推荐了,返回首页