Unityの忘備録です('◇')ゞ

自分用の忘備録です!

【Unity】マウススクロールでアイテムを切り替えるスクリプトを考えてみた!!

概要
リスト化されたアイテムをマウスククロールで選択し、プレイヤーの子オブジェクトの位置にインスタンス化する仕様です!
ご参考までに~

  using System.Collections.Generic;
  using UnityEngine;

  public class PlayerManageItems : MonoBehaviour
  {
    [SerializeField] int currentItemIndex;
    [SerializeField] Item currentItem; // Itemは別途作成したアイテムの情報を格納するスクリプト
    [SerializeField] List<Item> itemList; 
    [SerializeField] Transform itemInstanceTransform; // アイテムを実体化させる位置

    void Start()
    {        
        itemList = new List<Item>();        
        currentItemIndex = -1;
    }

    public void Update()
    {
        Selecte_Item();  
    }

    void Set_CurrentItem(int number)
    {
        if (number > -1)
        {
            currentItem = itemList[number];
        }
        else currentItem = null;
    }

    void Set_CurrentItemObject() // アイテムをプレイヤーの子オブジェクトの位置に実体化させる関数
    {        
        Destroy(currentItemObject);
        if (currentItem != null)
        {
            currentItemObject = Instantiate(currentItem.prefab, itemInstanceTransform);                
        }
    }

    public void Selecte_Item() //currentItemIndex = -1 は 何も手に持っていない状態にしたい
    {    
        if(itemList.Count == 0) return;

        if(Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            currentItemIndex++;
            if (currentItemIndex > itemList.Count - 1)//ListのIndex番号がアイテム以上に数になった時
            {
                currentItemIndex = -1;              
            }        
            Set_CurrentItem(currentItemIndex);
            Set_CurrentItemObject();                  
        }
        else if(Input.GetAxis("Mouse ScrollWheel") < 0)
        {            
            currentItemIndex--; 
            if (currentItemIndex < -1) //ListのIndex番号が-1未満になった時
            {
                currentItemIndex = itemList.Count - 1;
            }
            Set_CurrentItem(currentItemIndex);
            Set_CurrentItemObject();
        }
    }   

以上です!!

【Unity】ビルドしたらGameObjectのインスタンスが取得できなくなった!?

ビルドする前は下記スクリプトでGameObjectが取得できてましたが、
ビルドしたらなぜかインスタンスがNullのエラーがでました!

GameObject player;
void Start()
{
   player = GameObject.FindWithTag("Player");
}

下記のコードで対処しました!!

void Update()
{
   if (player == null)
   {
      player = GameObject.FindWithTag("Player");
   }
}

【Unity】特定のオブジェクトにのみディレクショナルライト(Directional Light)を当てる【忘備録】

試したUnityのバージョン:2022.3.13f1



ディレクショナルライトのインスペクターのカリングマスクという項目で設定できます。
この項目で選択されているレイヤーがアタッチされているオブジェクトに光が当たるようになっているみたいです。



今回はプレイヤーにのみディレクショナルライトを当ててみたいと思います。
まず、どのオブジェクトでもよいので右上のレイヤーのタブをクリックします。
そして、下の画像のようにレイヤーを追加をクリックします。



すると下の画像のようにレイヤーの行が出てくるので、空白部分に新しい名前を入力します。
空白であれば行は好きな番号でOKです。
今回は Illuminated by DirectionLight という名前にしました。



そして光を当てたいオブジェクトのレイヤーを上記で作成したレイヤーにします。



最後にディレクショナルライトのインスペクターのカリングマスの項目で上記のレイヤーのみを選択します。
初期設定ではすべてのレイヤーにチェックが入っているので、当てたくないレイヤーはチェックを外しましょう。
ちなみにライトの強さはディレクショナルライトのインスペクターの強さの数値で変更可能です。

© UTJ/UCL



おわり(-_-)zzz

【Unity】新しいNavmesh使ってみたら敵が部屋まで入ってこれない【忘備録】


問題:敵が部屋に入ってこれない!!


© UTJ/UCL



解決:古いNavmeshのベイクが残っており、2重になっていた
新しいNavmeshを使用する前に、古い方のNavmeshでベイクしていたから
そちらが優先されていたみたい。
古い方のベイクをクリアにして、新しいNavmeshをベイクしたところ
解決しました('◇')ゞ
新しいNavmeshをベイクする前にキャラクター達を非表示にしないと、
キャラクターがいる部分も障害物扱いになってしまうので注意が必要ですね!
他に上手いやり方あるかも。

【Unity】Rayが当たった物体の平面に対する角度を求める【忘備録】

平面とPlayerの正面との角度を求めたくて色々やってたらたどり着いた方法です('◇')ゞ
忘れないように( ..)φメモメモ





壁に対して真っすぐ向くと90度、左右を向くと数値減ります。
もっといい方法ありそう。。

void Angle()
   {
        Debug.DrawRay(transform.position + Vector3.up, transform.forward * 10);//Rayを見えるようにする

        if (Physics.Raycast(transform.position + Vector3.up, transform.forward, out RaycastHit hit, 10))
        {
            Vector3 ProjectOnPlane = Vector3.ProjectOnPlane(transform.forward, hit.normal);
            float angle = Vector3.Angle(transform.forward, ProjectOnPlane);
            Debug.Log(angle);
        }
   }


youtu.be

【Unity】平面に対して垂直に振り向く処理 (hit.Normal)【忘備録】

レイが当たった壁の面に対して垂直になるよう振り向く処理です。
色々使えそうなので忘備録として( ..)φ





void Rotation()
   {
        Debug.DrawRay(transform.position + Vector3.up, transform.forward * 10);//Rayを見えるようにする

        if (Physics.Raycast(transform.position + Vector3.up, transform.forward, out RaycastHit hit, 10))
        {
            //壁の方を真っすぐ向くように回転
            Quaternion rotation = Quaternion.LookRotation(-hit.normal);//-にしないと反対向いちゃう
            rotation.x = 0; rotation.z = 0;
            transform.rotation = rotation;
        }
   }




youtu.be

【Unity】壁に掴まる処理を実装しました【日記】



note.com
上記の記事をすごく参考にさせていただきました('◇')ゞ
落下中やジャンプ中にも壁を掴めるようにしてみました。ただ、淵より少し下を掴んでしまっている事や壁との距離感等、
改善する事がまだあるようです。。。





レイを2本出しました。
ジャンプして下から壁の淵まで到達した場合と、落下して上から壁の淵まで到達した場合を判別するには、下のレイが壁に当たっていて、
かつ、上のレイが壁に当たっていない状態なのだと考えました('◇')ゞ
下のレイは壁が目の前に在るかを検知、上のレイは淵まで来たかを検知する事としました。
下から淵までジャンプした場合、上のレイが False になった瞬間にフラグを立てる。
落下中に淵まで来た場合、下のレイが True になった瞬間にフラグを立てる、といった感じです。

   [Header("掴まる")]
   [SerializeField] float distance = 0.4f;//レイの長さ
   [SerializeField] float underRayOffset = 1.68f;//下のレイの高さ
   [SerializeField] float upperRayOffset = 1.8f;//上のレイの高さ
   [SerializeField] float wallandBodyOffset = 0.1f;//壁とPlayerとの隙間
   [SerializeField] bool isUnderRay;//下のレイが壁に当たっているか否か
   [SerializeField] bool isUpperRay;//上のレイが壁に当たっているか否か
   [SerializeField] bool grabFlag = false;//掴めるか否か
   [SerializeField] float coolTimeOfGrabing = 0;//次掴むまでのクールタイム

   public void Grab()
        {
            //壁検知用
            Ray underRay = new(transform.position + Vector3.up * underRayOffset, transform.forward);
            Debug.DrawRay(underRay.origin, underRay.direction * distance, Color.red);
            isUnderRay = Physics.Raycast(underRay, out RaycastHit hit, distance);//hitに壁の情報を格納
            
            //淵検知用
            Ray upperRay = new(transform.position + Vector3.up * upperRayOffset, transform.forward);
            Debug.DrawRay(upperRay.origin, upperRay.direction * distance, Color.red);
            isUpperRay = Physics.Raycast(upperRay, distance);

RaycastHitで下のレイの情報を格納します。
これは後からPlayerが壁に対して斜めにならないように調整する為です。
レイ同士の間隔ですが、
下からジャンプした場合、上のレイがFalseになった瞬間に掴みモードになるため、上下のレイの間隔は狭い方がよかったのだけれど、狭くしすぎると
なぜだか手くいきませんでした(゜-゜)



続きのコード

            //  isUnderRay = true で正面に壁があることを判断、isUpperRay = false で淵まで来たもしくは淵まで落下したかを判断。かつ、coolTimeが0.3f以上経過
            if(isUnderRay && isUpperRay == false && coolTimeOfGrabing > 0.3f & playerManager.isGrounded == false)
            {
                grabFlag = true;
            }

            if (grabFlag)
            {       
                if (playerManager.isGrabing == false)//まだ掴んだ状態でなければ実行
                {                    
                    playerManager.isGrabing = true;
                    rigidBody.isKinematic = true;//重力を無効化

                    //壁に密着するように調整                         
                    Vector3 position = transform.position + transform.forward * wallandBodyOffset;
                    transform.position = position;

                    //壁の方を向くように調整
                    Quaternion rotation = Quaternion.LookRotation(-hit.normal);//-にしないと反対向いちゃう
                    rotation.x = 0; rotation.z = 0;
                    transform.rotation = rotation;

                    animatorHandler.PlayTargetAnimation("Grab", false, 0.1f);//掴みアニメーション実行
                }
                else if (inputHandler.jump_southPress_Input)//ジャンプボタンで解除
                {
                    inputHandler.jump_southPress_Input = false;// falseにしないと何故かJumpしちゃう
                    playerManager.isGrabing = false;
                    rigidBody.isKinematic = false;
                    coolTimeOfGrabing = 0;
                    grabFlag = false;
                }
            }

            coolTimeOfGrabing += Time.deltaTime; 
        }

下のレイが壁に当たっていて、上のレイが壁に当たっていなくて、クールタイムが取れていて、地面にいない時に
掴むフラグがオンになって、重力が無くなり壁との隙間を埋めて壁と同じ向きに回転
するって感じです('◇')ゞ
掴んでいる最中にジャンプボタンを押すと掴みが解除されるようにしました。
クールタイムを入れた理由は掴みを解除した瞬間にまた掴んでしまうからです。



まだまだ改善点はあると思いますが、ひとまず壁に掴まれたので
自分的には満足しています( ^^) _旦~~
おわり