//tips
//shaderとは
プログラムを反映する中で、再度shaderについて理解し直す必要が生じたので記載する。
shaderシェーダーとは、描画方法を記述したプログラムと言え、描画の表現方法を変えてくれるものである。
いつもShaderの中のstandardを使用しているので、あまり意識していないが全てのオブジェクトはshaderの描画処理を行われて画面に反映されている。
まず、全ての3Dオブジェクトは、三角形の集合体により成り立っており、四角形だけでなく、球体も、三角形に丸みを与えたり引き伸ばしたりすることで、形成されている。
さらにこの三角形の描画に対しても、頂点を加工する処理→頂点に囲まれた中身のピクセル情報を加工する処理という流れに分解できる。
三角形の頂点各々に座標、色などの描画に必要な情報が組み込まれている。
この頂点の情報が決まったら、その中身をピクセルという点で埋め潰して、表示するのである。
Materialマテリアルとの違いは、マテリアルは、パラメーターをシェーダーに与えて、頂点やピクセルの配分などを計算させた外観を表すものであり、描画の計算方法を表すプログラミングであるシェーダーとは、その点で異なっている。
さらにこのシェーダーは自分で作成することができるものである。
//DrawCallとは
Unityの処理速度を向上させるためにはDrawCallドローコールを減らす必要があると言われている。
そのドローコールは、set pass callとも言われ、1フレーム描画するのに、CPUからGPUに対して何回描画命令を送っているかを示す値である。
描画命令にはそれなりの時間がかかるので、Set Pass Call数が少なければ少ないほど高いFPSを維持することができ、負荷が少なくなるため、なるべく小さなドローコール数が求められている。
この値はゲームシーンのstatusで表示されるset pass callから確認することができる。
一回のドローコールの中に
1. CPUからGPUにテクスチャ、マテリアル、座標等の値を渡す
2. GPUを走らせ、ポリゴンをレンダリング
3. CPUに処理を戻す
という処理が行われ、ドローコールが29であった場合は29回上記の処理が行われていることになる。
逆に、シェーダーを使って、GPUの処理を書き、一回で複数オブジェクトをレンダリングしてしまえば、複数個のオブジェクトを一度にレンダリングしても、1回のDrawCallで済むという方法も使われている。
http://wordpress.notargs.com/blog/blog/2015/01/28/unity%E6%9C%80%E9%81%A9%E5%8C%96%E3%81%AE%E8%A6%81%E3%80%8Cdrawcall%E3%80%8D%E3%81%A8%E3%81%AF%EF%BC%9F/
//ハイライトしたボタンをクリックして動作させる
現在はハイライト処理を行ったボタンにかかわらず、画面クリックするとwater showerの処理が実行されるので、ボタンの処理もスクリプトに反映させる。
このprojectでは単一クリック入力のみしか使用しないので入力をチェックするスクリプトを記載する。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Clicker : MonoBehaviour
{
public bool clicked()
{
return Input.anyKeyDown;
}
}
これによりどのようなスクリプトを書く際にも、ユーザーからのクリックを感知する場合にはClickerファイルを使用することができる。
clicked()でtrueかfalseを返すのだが、その条件はInput.anyKeyDownがされているか、されていないかで行うことができる。
Boolではreturnを使うことで間に変数への代入などを挟まなくて良いのでかなりシンプルで見やすいコードをかける。
このclicker()をButtonExecuteに反映して、Hoseに初めからついているスクリプトを外したらボタンが制御できるようになる。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class ButtonExecute : MonoBehaviour
{
private GameObject currentButton;
private Clicker clicker = new Clicker();
void Update()
{
//Transform camera = Camera.main.transform;
//Ray ray = new Ray(camera.position, camera.rotation * Vector3.forward);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
GameObject hitButton = null;
PointerEventData data = new PointerEventData(EventSystem.current);
if (Physics.Raycast(ray, out hit))
{
if (hit.transform.gameObject.tag == "Button")
{
hitButton = hit.transform.parent.gameObject;
}
}
if(currentButton != hitButton) {
if(currentButton != null)
{
ExecuteEvents.Execute(currentButton, data, ExecuteEvents.pointerExitHandler);
}
currentButton = hitButton;
if(currentButton != null)
{
ExecuteEvents.Execute(currentButton, data, ExecuteEvents.pointerEnterHandler);
}
}
if(currentButton != null)
{
if (clicker.clicked())
{
ExecuteEvents.Execute(currentButton, data, ExecuteEvents.pointerClickHandler);
}
}
}
}
//ジェスチャーなどのカメラ角度で操作する
VRでは頭の角度に紐づくカメラ角度によって操作を行わせることもできるので、そちらのスクリプトも確認する。
DetectFacingDownでカメラの角度が60度より小さいか確認する。
CameraAngleFromGroundを使用すると水平状態から現在のカメラの角度を0から180度の間で取得できる。
これにより常にカメラの角度が60度より小さいかどうかを判断し続けている。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeadGesture : MonoBehaviour
{
public bool isFacingDown = false;
void Update()
{
isFacingDown = DetectFacingDown();
}
private bool DetectFacingDown()
{
return (CameraAngleFromGround() < 60.0f);
}
private float CameraAngleFromGround()
{
return Vector3.Angle(Vector3.down, Camera.main.transform.rotation * Vector3.forward);
}
}
これでカメラの角度の検知ができたので検知したものをトリガーに呼び出し処理をする方法を考える。
HeadGestureの中のisFacingDownにより、ダッシュボードのx値を変更し、表示状態を切り替えてみる。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlippinDashboard : MonoBehaviour
{
private HeadGesture gesture;
private GameObject dashboard;
private bool isOpen = true;
private Vector3 startRotation;
void Start()
{
gesture = GetComponent();
dashboard = GameObject.Find("Dashboard");
Debug.Log(dashboard);
startRotation = dashboard.transform.eulerAngles;
CloseDashboard();
}
void Update()
{
if (gesture.isFacingDown)
{
OpenDashboard();
}
else
{
CloseDashboard();
}
Debug.Log("gesture.isFacingDown:" + gesture.isFacingDown);
}
private void CloseDashboard()
{
if (isOpen)
{
dashboard.transform.eulerAngles = new Vector3(180.0f, startRotation.y, startRotation.z);
isOpen = false;
}
}
private void OpenDashboard()
{
if (!isOpen)
{
dashboard.transform.eulerAngles = startRotation;
isOpen = true;
Debug.Log("open");
}
}
}
カメラ角度60度を境にしてダッシュボードの表示を上下逆にしている。
次にダッシュボードをカメラ角度60度を境に非表示から表示に切り替えるスクリプトに変えていく。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlippinDashboard : MonoBehaviour
{
private HeadGesture gesture;
//private GameObject dashboard;
[SerializeField] GameObject dashboard;
private bool isOpen = true;
//private Vector3 startRotation;
void Start()
{
gesture = GetComponent();
//dashboard = GameObject.Find("Dashboard");
Debug.Log(dashboard);
//startRotation = dashboard.transform.eulerAngles;
CloseDashboard();
}
void Update()
{
if (gesture.isFacingDown)
{
OpenDashboard();
}
else
{
CloseDashboard();
}
Debug.Log("gesture.isFacingDown:" + gesture.isFacingDown);
}
private void CloseDashboard()
{
if (isOpen)
{
//dashboard.transform.eulerAngles = new Vector3(180.0f, startRotation.y, startRotation.z);
dashboard.SetActive(false);
isOpen = false;
}
}
private void OpenDashboard()
{
if (!isOpen)
{
//dashboard.transform.eulerAngles = startRotation;
dashboard.SetActive(true);
isOpen = true;
Debug.Log("open");
}
}
}
[SerializeField] GameObject dashboard;を利用して、非表示の状態からでもsetactiveで表示できるようにしている。