2017年7月23日 星期日

Unity 呼叫 Java檔案

Unity 呼叫 Java檔案

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.unityplugin"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="25" />

    <application
        android:allowBackup="true"
        android:label="@string/app_name"
        android:supportsRtl="true" >
    </application>

</manifest>

//-----------------------
test.jar

package com.example.unityplugin;

public class pluginClass{
public static String getTextFromPlugIn(int Number){ return "Number"+Number}

}

PS 這兩個檔案丟到Asset/PlugIn/Android/lib底下
//-----------------------

PluginWrapper.cs



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

public class PluginWrapper : MonoBehaviour {

// Use this for initialization
void Start () {
        TextMesh textMesh = GetComponent<TextMesh>();
        ///<summary>packageName,className</summary>
        var plugin = new AndroidJavaClass("com.example.unityplugin.pluginClass");
        textMesh.text = plugin.CallStatic<string>("getTextFromPlugIn",7);
}
// Update is called once per frame
void Update () {
}
}

2017年4月6日 星期四

Unity 開啟攝影機

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

public class OpenCamera : MonoBehaviour
{
    /// <summary>顯示在此圖片上</summary>
    RawImage rimgShow = null;
    /// <summary>//接收攝影機返回的圖片數據</summary>
    WebCamTexture myCam;

    IEnumerator open_Camera()
    {
        //授權開啟鏡頭
        yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
        if(Application.HasUserAuthorization(UserAuthorization.WebCam))
        {
            //設置攝影機要攝影的區域
            //(攝影機名稱, 攝影機要拍到的寬度, 攝影機要拍到的高度, 攝影機的FPS)
            myCam = new WebCamTexture(WebCamTexture.devices[0].name, Screen.width, Screen.height, 60);
            rimgShow.texture = myCam;
            myCam.Play();//開啟攝影機
        }
    }
    // Use this for initialization
    void Start()
    {
        rimgShow = gameObject.GetComponent<RawImage>();
        StartCoroutine(open_Camera());//開啟攝影機鏡頭
    }
    /// <summary>開啟攝影機</summary>
    public void openCamera()
    {
        rimgShow.gameObject.SetActive(true);
        myCam.Play();//開啟攝影機
    }
    /// <summary>消滅</summary>
    void OnDisable()
    {
        //當程式關閉時會自動呼叫此方法關閉攝影機
        myCam.Stop();
    }
}


2017年3月27日 星期一

Unity 3D 移動公式 心得筆記

大家好,最近才領悟到心得筆記可以放在部落格,一來在自己找歷史資料時方便,二來也許整理的心得會有需要的人,也可方便取用,就這樣。

這邊若要活用移動方式,會建議學習向量相關的知識,會比較了解為何可以達到這種效果,但如果不學,看懂套用方式直接套用也可以,就看本身自己的需求如何了。

接下來介紹一下在Unity中,移動可分為 移動模式移動方式
移動方式又有分非物理影響物理影響的移動方式,因為我的專案目前還不需要用到,物理影響相關的公式,所以我這邊就不再特別介紹,等我需要的時候,再一併整理上來吧。

移動模式:移動中的路徑變化
  • Vector3.Lerp:根據來源地與目的地,兩點畫一直線做直線位移運動,以時間軸控制。
  • Vector3.Slerp:根據來源地與目的地,兩點畫一曲線做曲線位移運動,曲度由來源目標的物件方向與目的地的位置做角度偏移量決定。
  • Vector3.MoveTowards:與Vector3.Lerp做一樣的直線運動,控制項是以移動速度做為控制。
  • Vector3.SmoothDamp:與Vector3.Lerp做一樣的直線運動,但加入了時間軸控制與最大移動速度限制控制。
移動方式:移動時,是屬於跳耀方式還是連續性的位移
  • Transform.position:瞬間移動到定點位置 (較不受碰撞影響)。
  • Transform.Translate:平滑移動 (可受碰撞影響),會讓移動看起來更順,但需要位移時間。
可看需求搭配組合:
  • Transform.Position定點跳耀的移動方式需搭配對應的移動模式
  • Transform.Translate:本身就有支援直線位移的功能,所以只有非直線位移的方式,才需要額外撰寫移動模式。
接下來介紹實際使用的方式與內容。



Vector3.Lerp使用時機:
做直線運動時,並須要在特定時間內到達定點,或是想要在移動的過程中做漸快漸慢,因為是直線運動所以比較常跟transform.position做搭配使用。

函式宣告:
Vector3.Lerp(from : Vector3, to : Vector3, t : float) : Vector3
from:起始座標
to:目的座標
t:以時間軸控制位移[0, ... , 1],1秒鐘到達目的,0.5秒代表中間位置,所以自己要換算所需時間。
return:當下座標

使用範例:
public class example : MonoBehaviour {
 public Transform start;
 public Transform end;
 void Update() {
  transform.position = Vector3.Lerp(start.position, end.position, Time.time);
 }
}



Vector3.MoveTowards使用時機:
與Lerp一樣做直線運動,不一樣的地方是Lerp是控制時間軸,而MoveTowards是控制移動速度,當要做等速度移動或是保持某個速度移動時適用。

函式宣告:
Vector3.MoveTowards (current : Vector3, target : Vector3, maxDistanceDelta : float) : Vector3
current :起始座標
target :目標座標
maxDistanceDelta :保證移動時,不會超過我們設定的速度,正值就是追向目標,負值就是遠離目標。
return:當下座標

使用範例:
public class example : MonoBehaviour {
 public Transform start;
 public Transform end;
 void Update() {
  transform.position = Vector3.MoveTowards(start.position, end.position, 30.0f);
 }
}



Vector3.Slerp使用時機:從一個座標方向到一個目標座標畫一個弧線,使用時間軸控制位移座標,可以用於曲線移動到目標,比如火球術,或光球追跡彈。

函式宣告:
Vector3.Slerp (from : Vector3, to : Vector3, t : float) : Vector3
from:起始座標
to:目的座標
t:以時間軸控制位移[0, ... , 1],1秒鐘到達目的,0.5秒代表中間位置,所以自己要換算所需時間。
return:當下座標

使用範例:
public class example : MonoBehaviour {
 public Transform sunrise;
 public Transform sunset;
 void Update() {
  Vector3 center = sunrise.position + sunset.position * 0.5F;
  center -= new Vector3(0, 1, 0);
  Vector3 riseRelCenter = sunrise.position - center;
  Vector3 setRelCenter = sunset.position - center;
  transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, Time.time);
  transform.position += center;
 }
}



Vector3.SmoothDamp使用時機:這是Lerp與MoveTowards的功能總合版本,會以漸快的方式達到一個速度後,保持速度,當目標不再移動時,會已漸慢速度移動到目標位置,感覺就像開車停車一樣,保持較為平滑變化較小的位移狀態,最常見的用法用於攝影機跟隨目標。

函式宣告:
Vector3.SmoothDamp(current : Vector3, target : Vector3, ref currentVelocity : Vector3, smoothTime : float, maxSpeed : float = Mathf.Infinity, deltaTime : float = Time.deltaTime) : Vector3
current:目前所在位置
target:目的地位置
currentVelocity:當前的速度 是返回值
smoothTime:達到目標的時間設定
maxSpeed:最大移動速度限制
deltaTime:上次調用此函數的時間 默認Time.deltaTime
return:回傳 更新的座標位置

使用範例:
public class example : MonoBehaviour {
 public Transform target;
 public float smoothTime = 0.3F;
 private Vector3 velocity = Vector3.zero;
 void Update() {
  Vector3 targetPosition = target.TransformPoint(new Vector3(0, 5, -10));
  transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
 }
}



Transform.position使用時機:當不需要碰撞,而且希望更迅速更省效能的方式移動到我們想移動到的位置時,可以選擇此方法。

物件宣告:
Transform.position : Vector3
無法直接針對裡面的xyz做運算,當需要改變裡面的數值時可透過向量運算或是new的方式重新賦予座標位置。

Vector3本身可以表示成座標位置也可表示成速度向量,這邊就要看讀者怎麼解讀使用他了,
但在這邊的公式參數幾乎都是以座標位置為主 所以要當成速度向量的話,就需要做公式轉換寫成:
目的位置 = 來源位置 * 速度向量
這樣子就可以讓他在移動時不會到達目標點就停住了。

使用範例:
public class example : MonoBehaviour {
        //目標位置
 public Transform target;
 void Update() {
                //計算兩物體的距離
                float dis = Vector3.Distance(transform.position, traget.position);
                //保持距離,若遠離則追逐目標。
                if(dis >= 5) {
                        //持續注視目標
                        transform.LookAt(target);
                        //持續往目標前進
                        transform.position += transform.forward*Time.deltaTime * 1;
  }
 }
}



Transform.Translate使用時機:平滑移動 (可受碰撞影響),會讓移動看起來更順,因為在移動的過程,自己會去運算補間位移的過程,但移動到位置的時間會比較慢,而且在運算中比較容易耗效能。

函式宣告:
    以自身位置為基準:
    Transform.Translate (translation : Vector3, relativeTo : Space = Space.Self) : void
    Transform.Translate (x : float, y : float, z : float, relativeTo : Space = Space.Self) : void
    translation: 給予移動方向與速度
    relativeTo: 此速度向量是依照哪個座標系 Space.Self or Space.World

    依據目標位置 給予速度向量,設定移動距離
    Transform.Translate (translation : Vector3, relativeTo : Transform) : void
    Transform.Translate (x : float, y : float, z : float, relativeTo : Transform) : void
    translation: 速度向量
    relativeTo: 目標位置

使用範例:
public class example : MonoBehaviour {
 void Update() {
  transform.Translate(Vector3.forward * Time.deltaTime);
  transform.Translate(Vector3.up * Time.deltaTime, Space.World);
 }
}

Transform.Translate本身配合 Transform.Rotate 就可以使用控制角度的方式前進移動,移動會依照目前物件面向的方向一值前進,而我們可以透過Rotate改變他的移動角度。

使用範例:
public class example : MonoBehaviour {
 void Update() {
  transform.Translate(Vector3.forward * Time.deltaTime);
  transform.Rotate(Vector3.up * Time.deltaTime * 50.0f);
 }
}



飛機移動方式

public class OwnFighter : MonoBehaviour
{
    /// <summary>移動速度</summary>
    public float fMoveSpeed = 1.0f;
    /// <summary>旋轉速度</summary>
    public float fRotateSpeed = 5.0f;

    void Update()
    {
        //上下旋轉
        float l_fH = Input.GetAxis("Mouse X") * fRotateSpeed;
        transform.Rotate(Vector3.up * Time.deltaTime * l_fH * 100);
        //左右旋轉
        float l_fV = Input.GetAxis("Mouse Y") * fRotateSpeed;
        transform.Rotate(Vector3.left * Time.deltaTime * l_fV * 100);
        //往前移動
        transform.Translate(Vector3.forward * Time.deltaTime * fMoveSpeed);
    }
}


補充:

有鋼體的話可以用鋼體設定速度的方式讓他自行移動。
l_obj.GetComponent<Rigidbody>().velocity = transform.TransformDirection(Vector3.forward * 10);



以下也開放留言,可以問一些問題,可以再相互討論精進。