20210302のUnityに関する記事は4件です。

[Unity3D] シーンの切り替え・フェードイン/アウト

1, ヒエラルキーにPotalを作成し、RigidbodyとBoxColliderを作成する。各チェックとサイズを調整し、Prefabにする。
46878420-B6EA-4548-83C1-C87610FB0AD3.jpeg
43CA53AF-2A80-49AA-B7E7-3E129A45508A_4_5005_c.jpeg

2, PotalPrefabのLayer→IgnoreRaycastにする
D156A67B-844E-4C61-9F4B-0F6D13BD62EA_4_5005_c.jpeg

3, SceneManagementフォルダを作成しPotal.csを作成し、下記スクリプトを書く
3999E348-841C-422F-BC99-61D3F407ECEB_4_5005_c.jpeg

Portal
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace RPG.SceneManagement
{
    public class Potal : MonoBehaviour
    {
        [SerializeField] int sceneToLoad = -1;

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                SceneManager.LoadScene(sceneToLoad);
            }
        }
    }
}

4, PortalにPortal.csをアタッチし、SceneToLoadを1に設定する
AA85A522-B2D6-444A-A3AB-6153C50F023B.jpeg

5, BuildSettingでSceneを設定する
6EAAD168-B7A4-48F1-95A4-CA277C93016C_4_5005_c.jpeg

別シーンから戻る

1,下記コードを追加する

Potal
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace RPG.SceneManagement
{
    public class Potal : MonoBehaviour
    {
        [SerializeField] int sceneToLoad = -1;

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                StartCoroutine(Transition());
            }
        }

        private IEnumerator Transition()
        {
            DontDestroyOnLoad(gameObject);
            yield return SceneManager.LoadSceneAsync(sceneToLoad);
            Debug.Log("Scene Loaded");
            Destroy(gameObject);
        }
    }
}

SpawnPointの作成

1, Potalオブジェクト内にSpawnPointを作成する
C9D5C136-16D7-42E2-8EA2-59E485977A8F_4_5005_c.jpeg

2, SpawnPointを動かし、位置を決める
B24D9B79-E0A7-40B1-81C7-BAF02846F7CE_4_5005_c.jpeg

3, 下記コードを追加する

Portal
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.AI; // 追加

namespace RPG.SceneManagement
{
    public class Portal : MonoBehaviour
    {
        [SerializeField] int sceneToLoad = -1;
        [SerializeField] Transform spawnPoint;  //追加

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                StartCoroutine(Transition());
            }
        }

        private IEnumerator Transition()
        {
            DontDestroyOnLoad(gameObject);
            yield return SceneManager.LoadSceneAsync(sceneToLoad);

            Portal otherPortal = GetOtherPortal();    //追加
            UpdatePlayer(otherPortal);  //追加

            Destroy(gameObject);
        }

        //追加
        private void UpdatePlayer(Portal otherPortal)
        {
            GameObject player = GameObject.FindWithTag("Player");
            player.GetComponent<NavMeshAgent>().Warp(otherPortal.spawnPoint.position);
            player.transform.rotation = otherPortal.spawnPoint.rotation;
        }

        //追加
        private Portal GetOtherPortal()
        {
            foreach (Portal portal in FindObjectsOfType<Portal>())
            {
                if (portal == this) continue;

                return portal;
            }

            return null;
        }
    }
}

4, PotalのPotalスクリプトにSpawnPointを設定する
A5A2C306-F5FA-42F6-9680-82AE3A60F508.jpeg

5, SpawnPotalを回転させてplayerの向きを決める
9F963B44-5D4F-426F-AA80-664EE1A24063_4_5005_c.jpeg

6, PlayerのNavMeshAgentを外す
757A1E33-F833-4205-946C-AECF0AA64908_4_5005_c.jpeg

複数のSpawnpointの切り替え

1, 下記コメント部のコードを追加

Portal
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.AI;

namespace RPG.SceneManagement
{
    public class Portal : MonoBehaviour
    {
        //追加
        enum DestinationIdentifier
        {
            A, B, C, D, E
        }

        [SerializeField] int sceneToLoad = -1;
        [SerializeField] Transform spawnPoint;
        [SerializeField] DestinationIdentifier destination; //追加

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                StartCoroutine(Transition());
            }
        }

        private IEnumerator Transition()
        {
            //追加
            if (sceneToLoad < 0)
            {
                Debug.LogError("Scene to load not set.");
                yield break;
            }

            DontDestroyOnLoad(gameObject);
            yield return SceneManager.LoadSceneAsync(sceneToLoad);

            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);
            Destroy(gameObject);
        }


        private void UpdatePlayer(Portal otherPortal)
        {
            GameObject player = GameObject.FindWithTag("Player");
            player.GetComponent<NavMeshAgent>().Warp(otherPortal.spawnPoint.position);
            player.transform.rotation = otherPortal.spawnPoint.rotation;
            //player.transform.position = otherPortal.spawnPoint.position;
        }

        private Portal GetOtherPortal()
        {
            foreach (Portal portal in FindObjectsOfType<Portal>())
            {
                if (portal == this) continue;
                if (portal.destination != destination) continue;

                return portal;
            }
            return null;
        }
    }
}

2, Portalを作成し、Destinationのアルファベットを合わせる
8C722C7D-7FB2-4EDA-AC52-BC0E0089FE1F.jpeg

フェードアウトの作成

1, ヒエラルキーにUI→Canvasを作成する
63AA0FF7-5FDE-4F01-A41F-93E760DEC65E.jpeg

2, Faderに名前を変更し、CanvasGroupコンポーネントをつける
714B2CAB-1BAF-46B4-8C83-6F7C70462D63.jpeg

3, imageコンポーネントをつける
0A1C81EC-10CB-4635-982E-FC6EEFA5C143.jpeg

4, Fader.csを作成し、下記スクリプトを書く

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

namespace RPG.SceneManagement
{
    public class Fader : MonoBehaviour
    {
        CanvasGroup canvasGroup;

        private void Start()
        {
            canvasGroup = GetComponent<CanvasGroup>();

            StartCoroutine(FadeOutIn());
        }

        IEnumerator FadeOutIn()
        {
            yield return FadeOut(3f);
            Debug.Log("Fade out");
            yield return FadeIn(1f);
            Debug.Log("Fade in");
        }

        public IEnumerator FadeOut(float time)
        {
            while (canvasGroup.alpha < 1)
            {
                canvasGroup.alpha += Time.deltaTime / time;
                yield return null;
            }
        }

        public IEnumerator FadeIn(float time)
        {
            while (canvasGroup.alpha > 0)
            {
                canvasGroup.alpha -= Time.deltaTime / time;
                yield return null;
            }
        }
    }
}

5, Faderスクリプトをアタッチする
9392841E-2600-41A9-A0B4-CB937C890FB9.jpeg

6,CoreとFaderをPrefabにする
A9D922B8-CB05-41CB-A4BB-29A4056043C0_4_5005_c.jpeg

7, Scene2にCorePrefabから新しく作成する
475CB893-EE17-452F-B7E0-EAC8FF6A0084_4_5005_c.jpeg

8, PersistentObjectを作成し、Faderを子オブジェクトにしてからPrefabにする
EA73B877-F3A6-47EA-8BA1-2A402727716D_4_5005_c.jpeg

9,PersistentObjectSpawner.csを作成し、Coreにアタッチする
8352ECDC-4B79-438A-834C-5D11EF644D64.jpeg

10, 各スクリプトにコードを書く

PersistentObjectSpawner
using System;
using UnityEngine;

namespace RPG.Core
{
    public class PersistentObjectSpawner : MonoBehaviour
    {
        [SerializeField] GameObject persistentObjectPrefab;

        static bool hasSpawned = false;

        private void Awake()
        {
            if (hasSpawned) return;

            SpawnPersistentObjects();

            hasSpawned = true;
        }

        private void SpawnPersistentObjects()
        {
            GameObject persistentObject = Instantiate(persistentObjectPrefab);
            DontDestroyOnLoad(persistentObject);
        }
    }
}
Fader
using System.Collections;
using UnityEngine;
namespace RPG.SceneManagement
{
    public class Fader : MonoBehaviour
    {
        CanvasGroup canvasGroup;

        private void Start()
        {
            canvasGroup = GetComponent<CanvasGroup>();
        }

        public IEnumerator FadeOut(float time)
        {
            while (canvasGroup.alpha < 1)
            {
                canvasGroup.alpha += Time.deltaTime / time;
                yield return null;
            }
        }
        public IEnumerator FadeIn(float time)
        {
            while (canvasGroup.alpha > 0)
            {
                canvasGroup.alpha -= Time.deltaTime / time;
                yield return null;
            }
        }
    }
}
Portal
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
namespace RPG.SceneManagement
{
    public class Portal : MonoBehaviour
    {
        enum DestinationIdentifier
        {
            A, B, C, D, E
        }
        [SerializeField] int sceneToLoad = -1;
        [SerializeField] Transform spawnPoint;
        [SerializeField] DestinationIdentifier destination;
        [SerializeField] float fadeOutTime = 1f;
        [SerializeField] float fadeInTime = 2f;
        [SerializeField] float fadeWaitTime = 0.5f;

        //private void Start()
        //{
        //    transform.parent = null;
        //    DontDestroyOnLoad(gameObject);
        //}

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                StartCoroutine(Transition());
            }
        }
        private IEnumerator Transition()
        {
            if (sceneToLoad < 0)
            {
                Debug.LogError("Scene to load not set.");
                yield break;
            }

            transform.parent = null;
            DontDestroyOnLoad(gameObject);

            Fader fader = FindObjectOfType<Fader>();

            yield return fader.FadeOut(fadeOutTime);
            yield return SceneManager.LoadSceneAsync(sceneToLoad);

            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);

            yield return new WaitForSeconds(fadeWaitTime);
            yield return fader.FadeIn(fadeInTime);

            Destroy(gameObject);
        }

        private void UpdatePlayer(Portal otherPortal)
        {
            GameObject player = GameObject.FindWithTag("Player");
            player.GetComponent<NavMeshAgent>().Warp(otherPortal.spawnPoint.position);
            player.transform.rotation = otherPortal.spawnPoint.rotation;
        }
        private Portal GetOtherPortal()
        {
            foreach (Portal portal in FindObjectsOfType<Portal>())
            {
                if (portal == this) continue;
                if (portal.destination != destination) continue;
                return portal;
            }
            return null;
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Wallpaper Engineみたいに壁紙をUnityで作る

はじめに

今回は動く壁紙として有名なWallpapaer Engineのように、Unityで作ったプロジェクトを壁紙として表示する方法を書きます。

仕組み

壁紙のウィンドウハンドルを取得し、Unityのプロジェクトをそのウィンドウの子ウィンドウとして表示するだけです。

壁紙のウィンドウハンドル

c++で取得します。この記事ではc++でdllを作り、c#で呼び出します。

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL);
    HWND* ret = (HWND*)lParam;

    if (p)
    {
        *ret = FindWindowEx(NULL, hwnd, L"WorkerW", NULL);
    }
    return true;
}

HWND get_wallpaper_window()
{
    HWND progman = FindWindow(L"ProgMan", NULL);
    SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
    HWND wallpaper_hwnd = nullptr;
    EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd);
    return wallpaper_hwnd;
}

Unityを表示する

[DllImport("WallpaperDLL.dll")]     //c++で作ったdllを呼び出す
static extern IntPtr GetWallpaperHWND(); 

/*------------------------------------------*/

var path = ユニティーのexeのパス;
var cmdline = $"-parentHWND {GetWallpaperHWND()}";//子ウィンドウとして起動
Process exe = Process.Start(path, cmdline);

完成

二つ作ってみました。結構いい感じにできてよかったです。

ソース

DLL

最後に

結構簡単なのでぜひ試してみてください

参考

https://yotiky.hatenablog.com/entry/unity_uaal-wpf
https://stackoverflow.com/questions/56132584/draw-on-windows-10-wallpaper-in-c

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Wallpaper Engineみたいな壁紙をUnityで作る

はじめに

今回は動く壁紙として有名なWallpapaer Engineのように、Unityで作ったプロジェクトを壁紙として表示する方法を書きます。

仕組み

壁紙のウィンドウハンドルを取得し、Unityのプロジェクトをそのウィンドウの子ウィンドウとして表示するだけです。

壁紙のウィンドウハンドル

c++で取得します。この記事ではc++でdllを作り、c#で呼び出します。

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL);
    HWND* ret = (HWND*)lParam;

    if (p)
    {
        *ret = FindWindowEx(NULL, hwnd, L"WorkerW", NULL);
    }
    return true;
}

HWND get_wallpaper_window()
{
    HWND progman = FindWindow(L"ProgMan", NULL);
    SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
    HWND wallpaper_hwnd = nullptr;
    EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd);
    return wallpaper_hwnd;
}

Unityを表示する

[DllImport("WallpaperDLL.dll")]     //c++で作ったdllを呼び出す
static extern IntPtr GetWallpaperHWND(); 

/*------------------------------------------*/

var path = ユニティーのexeのパス;
var cmdline = $"-parentHWND {GetWallpaperHWND()}";//子ウィンドウとして起動
Process exe = Process.Start(path, cmdline);

完成

二つ作ってみました。結構いい感じにできてよかったです。

ソース

DLL

最後に

結構簡単なのでぜひ試してみてください

参考

https://yotiky.hatenablog.com/entry/unity_uaal-wpf
https://stackoverflow.com/questions/56132584/draw-on-windows-10-wallpaper-in-c

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityでiOSのUIColorPickerViewControllerを使うPlugin

はじめに

iOS14から導入されたUIColorPickerViewControllerをUnityから使いたかったのでPluginを書きました。

レポジトリ

Unitypackage

UIColorPickerManager.unitypackage

Sample

public void Show(){
    Color currentColor = Color.white;
    UIColorPickerManager.Show(currentColor, OnSelectColor, OnFinish);
}

// call when color selected.
void OnSelectColor(Color selectedColor){
    // ...
}

// call UIColorPickerViewController finished.
void OnFinish(){

}

UIColorPickerManager.Show

UIColorPickerManager.Show にはいくつかのオーバーライドがあります。

選択された色をColorオブジェクトで受け取る

void Show (
    Color currentColor,
    OnColorSelectedCallback onColorSelectedCallback,  // Colorオブジェクトを受け取るコールバック関数
    OnFinishCallback onFinishCallback)

選択された色をRGBAで受け取る場合

void Show (
    Color currentColor,
    OnRGBColorSelectedCallback onRGBColorSelectedCallback,  // RGBAを受け取るコールバック関数
    OnFinishCallback onFinishCallback)

選択された色をColorオブジェクトで受け取り、iOS14未満の時の処理を必要とする場合

void Show (
    Color currentColor,
    OnColorSelectedCallback onColorSelectedCallback,
    OnFinishCallback onFinishCallback,
    OnEarlierIOSVersionsCallback onEarlierIOSVersionsCallback)

選択された色をRGBAで受け取り、iOS14未満の時の処理を必要とする場合

void Show (
    Color currentColor,
    OnRGBColorSelectedCallback onRGBColorSelectedCallback,
    OnFinishCallback onFinishCallback,
    OnEarlierIOSVersionsCallback onEarlierIOSVersionsCallback)

参考:上記のコードで使われているdelegateの定義

    // - colorPickerViewControllerDidSelectColor: 用コールバック
    public delegate void OnColorSelectedCallback(Color color);
    public delegate void OnRGBColorSelectedCallback (float r, float g, float b, float a);

    // - colorPickerViewControllerDidFinish: 用コールバック
    public delegate void OnFinishCallback();

    // @available(iOS 14.0, *) がfalseの時用コールバック
    public delegate void OnEarlierIOSVersionsCallback();

ライセンス

ライセンスはMITです。

補足

いないかもしれませんが、ソースコードを読みたいという方がいれば、
先に、 [Unity]ネイティブプラグインからコールバック関数を呼ぶ[iOS]
という記事を読むことをお勧めします。このプラグインは、その記事の応用になっています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む