UnityでPlayerが動く度にHPが減少していく機能の作成

以前、FPS視点で動くPlayerを制御する方法を紹介しました。

移動しているときのみに、HPを減少させたいので
velocityを使っていきます。
velocity.magnitudeというパラメータを使うことで、velocityの大きさを取得することができます。

 private Rigidbody rb;

void Update()
{
// ココから 以前の記事で紹介した動く操作方法
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
transform.Rotate(0,x,0, Space.World);
float angleY = (360 - transform.eulerAngles.y + 90) % 360;
float radian = angleY * Mathf.Deg2Rad;     
float sin = Mathf.Sin(radian);     
float cos = Mathf.Cos(radian);     
rb.velocity = new Vector3(cos, 0, sin) * z;
// ココまで 以前の記事で紹介した動く操作方法 

// velocityが動いているときのみ処理する 
if (rb.velocity.magnitude > 0)     
{         
 // velocityの大きさを引数にした関数を作成
updateHP(rb.velocity.magnitude);     
}

}


private void updateHP(float deltaHPacc) {
\\floatでHPを減少させていき
HPacc -= deltaHPacc;     
 \\intへキャスト
 HP = Mathf.RoundToInt(HPacc);     

}
 

C#で、計算は小数点・表示は整数を実現する方法

どういったシチュエーションを想定しているかというと
HP 100 から減少していくが、整数で減少するよりももっと細かい減少を表現したいときなどです。

//floatで減少
HPfloat -= deltaHPacc;     

\\最大値は越えずに,0以下にもならない
if ( HPfloat  >= (float)maxHP)     
{ HPfloat  = (float)maxHP;     } 
else if ( HPfloat  <= 0f)
{ HPfloat  = 0;     }   

//整数に変換
HP = Mathf.RoundToInt(HPacc);

Unity positionの1つだけを変更する方法

今回は、position(Vector3 (x, y, z))の1つの要素だけを変更する方法を紹介します。

非常に簡単です。

        Vector3 pos = transform.position;
        pos.y = 0.1f;
        transform.position = pos;

y座標のみを変更するコードを記載しました。
positionを変更したい場合には、positionのデータ型で代入してあげる必要があります。( Vector3 (x, y, z) を想定)。
なので、下記のように1つのデータのみを選択して、代入することは出来ません。

//これは出来ない!!
transform.position.y = 0.1f;

prefabを一定時間間隔で生成する方法

今回は、Unityでのゲーム作りでは欠かせないprefabについてお話していきます。

( 1 ):一定時間間隔で処理を実行する
( 2 ):prefabを生成する

( 1 ):一定時間間隔で処理を実行する

幾つか、豊富はあるようですが
一番簡単そうな処理は、 InvokeRepeating 関数をです。

InvokeRepeating("UpdateMakePrefab", START, INTERVAL);

#UpdateMakePrefab → 繰り返し処理を実行したいメソッド名
#START → 一番最初に起動する時間
#INTERVAL → 更新する時間間隔

( 2 ):prefabを生成する

prefabを生成する関数は
Instantiate()という関数を使います。

Instantiate(prefabオブジェクト, prefabのposition, prefabの向き);

一定時間間隔で、prefabを生成するコード最後にまとめたいと思います。

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class makePrefab : MonoBehaviour
 {
     // public でInspectorから、生成したいprefabを紐付けておきます。
     public GameObject makeprefab;

     private const float START = 0.0f;
     private const float INTERVAL = 5.0f;
 
     void Start()
     {         InvokeRepeating("UpdateMakePrefab", START, INTERVAL);
     }
  
 
     private void UpdateMakePrefab() {

Instantiate(makeprefab, new Vector3(Random.Range(-5.0f, 5.0f),0, Random.Range(-5.0f, 5.0f)), Quaternion.identity);
     }
 
 }
 

UnityでFPS視点のPlayerを作る方法

今回は、FPS視点のPlayerの動きを制御していきます。
どういことかと言うと、
・回転操作
・直進操作
を別々に制御するということです。

以前、CameraをPlayer視点に紐付ける方法を紹介しました。
これだけでは、FPS的な動きを制御することは出来ず、Playerの動きも制御して上げる必要があります。

PCで制御することを前提に、コードを紹介します。
矢印Keyを読み取る、x・ z 変数を用意します。
最終的にやりたいのは、
・xのとき(矢印キーでいう左右)は、Playerの向きをコントロール
・zのとき(矢印キーでいう上下)は、Playerの前進・後退をコントロール
するということです。

x = Input.GetAxisRaw("Horizontal");
z = Input.GetAxisRaw("Vertical");

(1):矢印キーの左右に対して、Playerの向きをコントロールする。

float x = Input.GetAxis("Horizontal");
transform.Rotate(0,x,0, Space.World);

以前、UnityのRotateについて記事を書いたのでご確認ください。
y軸を回転させることで、x軸・z軸との面に対して回転します。

(2): 矢印キーの上下に対して、Playerの向きを前進と後退を制御する

    float z = Input.GetAxis("Vertical");

矢印キーの上下インプットを取得します。
重要なことは、 矢印キーの上下に対してPlayerが向いている方向に対して前進・後退をする必要があります。
sin cos を用いて、velocityを制御していくことで実現させます。
幾つかのステップに分けて説明していきます。

(a):Playerの向いている角度をsin,cosのΘの変化に対応するように調整
(b): オイラー角度 → ラジアンへ変更
(c): velocityへx軸、z軸方向へ代入

(a):Playerの向いている角度をsin,cosのΘの変化に対応するように調整

float angleY = ((360 - transform.eulerAngles.y) + 90) % 360;

transform.eulerAngles.y でPlayerが向いているオイラー角度を出力します。
ここで確認したいことは、Playerが向いている角度と、角度の変化です。

sin cos を利用していきます。
高校の数学で学んだ、あれです。
右向きにx軸・上向きにy軸・反時計回りにΘが増加していく、あれです。

Unity上でのPlayerの向いている角度を  transform.eulerAngles.y で確認すると
時計回りに角度が増加していきます。
なので、ここを修正すると
360 - transform.eulerAngles.y //①
z軸の方角が角度が0になっており、x軸に対して角度を0に変えたいので
(360 - transform.eulerAngles.y) + 90)//②
ただ、これだと、90~450度の範囲内になるので
((360 - transform.eulerAngles.y) + 90) % 360//③

(b): オイラー角度 → ラジアンへ変更

    float radian = angleY * Mathf.Deg2Rad;

(c): velocityへx軸、z軸方向へ代入

float sin = Mathf.Sin(radian);     
float cos = Mathf.Cos(radian);     
rb.velocity = new Vector3(cos, 0, sin);

これで、向いてる角度に前進、後退をするPlayerができます。

Unityで、FPS視点のCameraを作成する方法

FPSゲームが盛り上がっていますね。
今回は、FPS視点のCameraを作る方法について解説します。

▼簡単に流れ
( 1 ):Playerの子階層に、新しくGameObject cameraFollowを作成
( 2 ):Main camera に New Scriptを追加
( 3 ):GameObject cameraFollow に、Main Camera position, rotationを紐づける

( 1 ):Playerの子階層に、新しくGameObject cameraFollowを作成

Hierarchy でPlayerの子階層にgameobjectを追加

cameraFollow の positionにMain cameraのpositionをもってきます。
好きな位置でいいです。
※注意したいのは、ここのpositionはPlayerに対しての相対的なpositionになること。

( 2 ):Main camera に New Scriptを追加

Hierarchyの中の、MainCameraを選択した状態で、
Add Component → New Script

( 3 ): GameObject cameraFollow に、Main Camera position, rotationを紐づける

(2)で作成したMain Cameraのscriptにコードを書きます。

void Update() {     

\\ cameraFollow はPlayerの子階層に作成したgameobject
transform.position = GameObject.Find(" cameraFollow ").transform.position; 
   
transform.rotation = GameObject.Find(" cameraFollow  ").transform.rotation; 

}

Unity初心者がRotationを理解するための第一歩

transform.rotationは
Quaternion というデータフォーマットを基に決定されています。

一般的に利用されているオイラー角度(360度で1回転)とは異なる概念で、
直感的な理解が難しいと思います。

Inspector上では、オイラー角度で表示されているし、変更もできると思う方もいるかもですね。
どうやら、Inspecterに表示の際はQuaternion→オイラーへ変換されて表示されているようです。

つまり、
Quaternion と オイラー角度 はお互いに変換可能な数値ということです。

Quaternion.eulerAngles : 
Quaternion → オイラー角への変換メソッド

Vecto3 型で、(x軸の角度,  y軸の角度, z軸の角度)というデータ
数値はfloat
transform.rotation.eulerAngles で、transformのオイラー角度が算出

https://docs.unity3d.com/ja/540/ScriptReference/Quaternion-eulerAngles.html

Quaternion.Euler :
オイラー角 → Quaternionへの変換メソッド
上記、Quaternion と オイラー角度 を変換させる方法を説明してきました。

これらを用いれば、オイラー角度を用いて、rotationを操作する方法も可能ということです。

しかし、オイラー角度を用いた簡単な方法があります。
それがRotateメソッドです。

Transform,rotate(x, y, z, relativeTo )
x軸・y軸・z軸に対して、Transformを回転させる角度を変更することが可能です。
現在のTransformに対して、角度を加算します。

relativeToとは
ローカル座標を基準にするのか ・ ワールド座標を基準にするのかを指定することが出来ます。

x, y, zは、オイラー角度で、数値はflaot

Unity 時間差でSceneを遷移する方法

本日はScene遷移の方法を、時間差で実行します。
対戦型ゲームを作っていて、勝敗がついた後に、Sceneを遷移したいけれども時間を置いてから遷移したいとき等に活用できると思います。

(1):Scene遷移の方法を簡単に紹介
(2):遷移方法に時間差を付ける処理を追加

(1):Scene遷移の方法を簡単に紹介

a:Sceneを追加
b:空のGameObjectを追加
 → C#スクリプト(toFinish classを作成) をAdd component
c:scriptを編集
d:遷移したいタイミングでSceneManager.LoadScene()を含んだ処理を呼び出す

#classに継承しておく。SceneManagerを使えるようにする
using UnityEngine.SceneManagement;

#関数内で処理を実行する宣言をしておく
public class toFinish : MonoBehaviour
{ 
   public void OnfinishGame()
   {
   SceneManager.LoadScene("Sceneの名称");
   }
}

(2):遷移方法に時間差を付ける処理を追加

一番簡単に時間差を作れる、Invokeを呼び出して見ましょう。
遷移したいタイミングの関数をfinish()とした際に

private void finish ()
{
        //3秒後にCall関数を実行する
        Invoke("Call", 3f);
 }
}

void Call()
{
  #遷移する処理を呼び出し
    OnfinishGame();
}

UnityのCanvas RenderModeについて深堀りしてみたVer2

以前、UnityのCanvasについて紹介しました。
Render ModeをScreen-Space Cameraについてお話しました。
Screen-Space Cameraとは、CameraのViewの範囲の特定エリアに常にCanvasを配置しておく、といった設定でした。

今回は、World Spaceについて深堀りしてみたいと思います。

通常の使い方でいうと、Scene全体を示す World SpaceにCanvasを貼り付けることを想像する人もあるかもしれないですが、今回は特定Objectに対してWorld Spaceを設定することです。

特定のObjectをA Objectとした際に、Aを親・Canvasを子としてRender ModeをWorld Spaceに設定します。

そうすることで何が出来るようになるかと言うと、
特定のObject Aに対して、クッツイた状態のCanvasが設定することが出来るのです。
イメージがつきますでしょうか??

よくある例でいうと
・ゲームのHPを特定のPlayerにクッツイた状態で表記
・Playerに表記する矢印キーをくっついた状態で表記
など色々と応用可能かと思います。

UnityのCanvasのRender Modeについて深堀りしてみた

Render Modeについて調べていたら、めちゃくちゃ分かりやすい記事に出会いました。
https://light11.hatenadiary.com/entry/2019/04/15/232416

で、これでも相当理解できたのですが、
Render ModeをScreen-Space Cameraの理解を深めました。
というか、Canvasのサイズに起因している要素について2つのパラメータが影響しています。

(1):CanvasをScene上に配置してください。
(2):Render ModeをScreen-Space Cameraへ変更
(3):Render Mode > Render CameraにMain Cameraを設置

ここまで前準備で行ってみてください。

ここから調整してみて欲しいパラメーターは
①:Canvasの Plane Distance
②:Main Cameraの Field of View

この2つのパラメータを調整してみると、Canvasのサイズも同時に変化していることが分かると思います。
当たり前と言えば当たり前なのですが(Screen-Space CameraはCameraのサイズにFitしたCanvasなので)

実際に、パラメーターを調整してみると、Screen-Space Cameraがどんな設定なのか分かると思います。