わかゲームスタジオ

ゲーム制作初心者専門学生の備忘録

UE4 なんかいい感じのマテリアルを作る

今日教えていただいたことを復習がてら忘れないように残しておく回です。

 

↓今日できること↓

 

まずは上の方を作っていきます。

①マテリアルの作成

f:id:WakaiGames:20201025003553j:plain

  • これはいつものやつです。
  • 何となくUserIntarfaceにしています。

②テクスチャ設定

f:id:WakaiGames:20201025004000p:plain
f:id:WakaiGames:20201025003956p:plain
  • TextureSampleを右クリック後、テクスチャオブジェクトに変換をクリックします。
  • テクスチャは標準で入っているT_Noise01がおすすめ(と言われました。)です。

③今回のキモになる部分

f:id:WakaiGames:20201025004515p:plain
f:id:WakaiGames:20201025004512p:plain
  • まずは何もない場所で右クリック、MaterialFunctionCallを呼びます。
  • 詳細パネルから、4WayChaosを選択します。これは指定したテクスチャを斜め4方向に動かしてくれるノードです。(浅い知識)

④残りのノードを組む

f:id:WakaiGames:20201025005043p:plain

  • カラーParamは4を押しながらクリック後、そのノードを右クリックでParameterに変更できます。
  • MultiplyはMを押しながらクリックです。

以上で一つ目終了です。

色とテクスチャの組み合わせ次第で何十通りにも化けてくれそうですね。

 

次は

これを作ります。

①マテリアルの作成

f:id:WakaiGames:20201025010514j:plain

  • BlendModeとTwoSidedを変更します。TwoSidedは裏面も描画するかの設定です。

②ノードを組む

f:id:WakaiGames:20201025010810p:plain

  • ColorParameterには2500,0,0,0を代入しています。色の明るさを設定しています。
  • 緑のParameterはsを押しながらクリックで出せます。初期値は10です。ラインの太さを設定しています。
  • DepthFadeはオブジェクトの接地面を薄くしてくれるノードです。これを1-で反転、つまりオブジェクトとの接地面のみ描画するわけです。

これを適当なスフィアに適応すると、

 

以上です。今日教えてもらった内容でマテリアルが少しわかったように勘違いすることができました。楽しいですね。

現在制作中のゲームにも使用しようと思います。

UE4 キャラクターの違うマルチプレイを実現する

↓今回できること↓

 

①レベルブループリントにスポーン処理を書く

f:id:WakaiGames:20201020183436p:plain

  • CreatePlayerでPawnとそれに付随したPlayerControllerを作ります。
  • 上記のControllerから付いているPawnを変数に格納しておきます。
  • 上記のControllerとPawnの付随関係をUnPossesで外します。
  • CreatePlayerで作ったPawnはもう必要ないのでDestroyします。
  • 新しく実際に操作するActorを生成(位置はわかりやすいようにLevel上に配置したPlayerStartを使用しています。)
  • 新しく生成したActorにCreatePlayerで作成したPlayerControllerを付けます。

これをPlayer数分書くと、

 

こうなるわけですね。

これをIさんに手取り足取り教えていただきました。

ありがとうございました。

 

UE4 UIをWorld座標に表示する

↓今回やること↓

 

①表示したいWBPの作成

f:id:WakaiGames:20201020151047p:plain

  • TargetLocationには基準にしたいLocationを表示するBP側から代入します。
  • Set Alignment in ViewportのAlignmentを調整すると表示される位置のずれを設定できます。

②WBPを生成する

f:id:WakaiGames:20201020151314p:plain

  • これはいつもと同じですね。

こうすると、

 

以上です。

なんて簡単。

 

※追記

コンポーネントWidgetが追加できるらしい。

f:id:WakaiGames:20201020160243p:plain

  • 赤色のところでWBPを選択
  • 青色のところで表示のずれを指定できます。

f:id:WakaiGames:20201020160435p:plain

  • GetPlayerCameraManagerでカメラを取得
  • そこからLook at Rotationでカメラの方を向いてもらいます。

 

こっちの方が簡単やん。

壁を透過するしないの違いがあるので使い分けられそうですね。

Unity 構造体の作り方

Unityでは構造体ではなくClassで管理することが多いです。

非常に便利なので覚えておくと良いですね。

>|C#|

[System.Serializable]

public class Data

{

public string name;

public int id;

public int score;

public float time;

}

public Data[] data;

||<

大事なのは[System.Serializable]の部分です。

これがないと使えないので注意ですね。

 

こうするとinspector上では

f:id:WakaiGames:20201017222721p:plain

ちゃんと表示されていますね。

 

これを配列にすると

f:id:WakaiGames:20201017222806p:plain

より多くの情報を扱うことができるようになります。

 

以上です。

これすっごく便利。

Unity RigidbodyとRootMotionの共存

現在制作中のゲームで攻撃の踏み込みをRootMotionで、移動や回避をRigidbodyで実装したいと考えていたのです。
しかしどうしてもうまくいかず、試行錯誤の結果RigidbodyとRootMotionは共存できないという結論に至りました。

否、解決策あった。

以下のサイト様を参考(書いてあることまんま)にすると。
qiita.com

    void OnAnimatorMove()
    {
        transform.position = GetComponent<Animator>().rootPosition;
    }

このコード書くだけで良かったんだって。
これは便利!

Unity プレイヤーの回転をなめらかにしたい

瞬時に入力方向を向いても良いのですが、なめらかに向いても良いと思うのです。
というわけで今回はなめらかな振り返りを実装しようと思います。

↓今回できること↓

前回までの記事を先に読んでください。
wakagamestudio.hatenablog.jp


Unity ver.2019.3.4f1

①変数を追加

    [Header("回転速度")]
    [SerializeField]
    private float rotateSpeed;
  • 回転速度を決める変数です。

②前回書いた分を削除

    //===向き切り替え===//
    if (inputVector != Vector2.zero)
    {
        // キャラクターの向きを進行方向に
        transform.rotation = Quaternion.LookRotation(moveVector);
    }
  • 回転部分を書き換えます。

③削除部分にコードを追加

    Vector3 dirMoveVector = (moveVector + transform.position) - gameObject.transform.position;
    Vector3 cross = Vector3.Cross(transform.forward, moveVector);
    if (hori != 0 || ver != 0)
    {
        if (cross.y <= 0)
        {
            transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y - rotateSpeed, 0);
        }
        else
        {
            transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y + rotateSpeed, 0);
        }
    }
  • 向いている方向と向きたい方向で外積を取ります。

すると、


以上です。
操作性が極端に悪くならない限りはこれのほうが滑らかでよいかもしれませんね。

これまでの全コード

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

public class PlayerMovement : MonoBehaviour
{
    [Header("リジッドボディ")]
    [SerializeField]
    private Rigidbody rigidbody;

    [Header("移動速度")]
    [SerializeField]
    private float speed = 15;

    [Header("入力制限")]
    [SerializeField]
    [Range(0, 1)]
    private float inputLimit = 0.1f;

    [Header("回転速度")]
    [SerializeField]
    private float rotateSpeed;

    //入力値代入用
    private Vector2 inputVector;
    //移動方向決定
    private Vector3 moveVector;

    void Update()
    {
        //入力値を代入
        float hori = Input.GetAxis("Horizontal") >= -inputLimit && Input.GetAxis("Horizontal") <= inputLimit ? 0 : Input.GetAxis("Horizontal");
        float ver = Input.GetAxis("Vertical") >= -inputLimit && Input.GetAxis("Vertical") <= inputLimit ? 0 : Input.GetAxis("Vertical");
        inputVector = new Vector2( hori, ver);

        //カメラの向きから移動方向を決定
        moveVector = (Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized * inputVector.y + Camera.main.transform.right * inputVector.x) * speed;

        Vector3 dirMoveVector = (moveVector + transform.position) - gameObject.transform.position;
        Vector3 cross = Vector3.Cross(transform.forward, moveVector);
        if (hori != 0 || ver != 0)
        {
            if (cross.y <= 0)
            {
                transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y - rotateSpeed, 0);
            }
            else
            {
                transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y + rotateSpeed, 0);
            }
        }
    }

    private void FixedUpdate()
    {
        //移動方向に重力分を足す
        rigidbody.velocity = moveVector + new Vector3(0, rigidbody.velocity.y, 0);
    }
}

Unity 爆弾を実装する

以前のゲームジャムで爆弾を実装するときに参考になるサイトが見つからなかったので残しておきます。

Unity ver 2019.3.4f1

↓今回できること↓




①エネミーを作成

f:id:WakaiGames:20200922164348p:plain

  • Enemyタグを追加、設定

②爆弾用オブジェクト作成

f:id:WakaiGames:20200922164802p:plainf:id:WakaiGames:20200922164017p:plain

  • 爆発範囲用コライダー追加
  • 爆弾自体の当たり判定は子構造にしておきます。

③爆弾側にスクリプトを追加

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

public class BombAction : MonoBehaviour
{
    //範囲内にいるEnemyを保存するためのリスト
    private List<GameObject> enemys;

    private void Start()
    {
        //リストを初期化
        enemys = new List<GameObject>();
    }

    private void OnTriggerEnter(Collider other)
    {
        //進入オブジェクトがEnemyタグを持っているかつ、リスト外
        if (other.transform.tag == "Enemy" && !enemys.Contains(other.gameObject))
        {
            enemys.Add(other.gameObject);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        //出て行ったオブジェクトがEnemyタグを持っている
        if (other.transform.tag == "Enemy")
        {
            enemys.Remove(other.gameObject);
        }
    }

    //爆発処理
    private void Explosion()
    {
        print("Bomb");
        foreach (GameObject item in enemys)
        {
            //リスト内のオブジェクトを破壊
            Destroy(item);
        }
        //爆弾自身も破壊
        Destroy(gameObject);
    }
}

④爆発関数を実行

    IEnumerator Exp()
    {
        yield return new WaitForSeconds(2.5f);
        Explosion();
    }
  • 先のままでは爆発しないので関数呼び出し用コルーチンを書いておきます。
  • これをStartで呼び出します。

すると、

以上です。
foreach文内でEnemyにアタッチしたクラスをGetして、ダメージ処理を書いておくと即死ではなくダメージを与えることができます。
ゲームに応じて使い分けてみてください。