見出し画像

カメラ機能を拡張する コウペンちゃんランド#007

こんにちは、ふにいちごです🍓
久しぶりの進捗記事となります。
今日は以前に原型を実装したカメラ機能を拡張したのでそのお話です。

ただのスクショじゃつまらない!

前回までの実装では、カメラ機能はキーボード操作で写真用カメラに切替え、その映像を出力するだけでした。
が、撮る角度を変えたり、ズームをしたり、内カメ外カメ切り替えたりしたい!もっとコウペンちゃんを撮影してる感ほしい!
ということで、前回のカメラ機能から拡張する形で以下の機能を実装しました。

  • 操作をとりあえずGUIからに限定する

  • カメラの距離を調整するスライダーをつける

  • カメラの向きを自分向き(内カメ)と外向き(外カメ)とで切り替えれるようにする

  • カメラの角度をちょっとずつ調整できるようにする

  • 写真を撮ったあと、イメージを数秒表示させて撮ったよ感をアピール

そんな感じで出来たのがこちらの動画になります。

正直この形に行きつくまでに行ったり来たりを繰り返していたので、すべての過程を覚えているわけではないのですが、
とりあえずイメージに近しいものはできました。
外向きカメラのとき、プレイヤーを突き抜けてポリゴンの裏側に入っちゃう(プレイヤーが透けちゃう)のを直したいところですが、
遠くからプレイヤーを見る写真も撮れるかなと思ったりもするので悩みどころです。
でもやっぱり透けちゃうのは変💦
また、コウペンちゃんが再び周りを歩き始めたら、そこに向けてのズームとかもしたくなる気がします。

ゲームを作り始めて感じたのですが、慣れていないせいもあって行ったり来たりがとても多いです。
仕様をしっかりと決めていないからな気もしますが、かっちりとした仕様を切れる気もしない。
また後日の記事でカメラ機能変えたよ~となる気もしますが、一区切りとして記録しておきます。

スクリプトメモ

前提として、各GUIはUIControllerクラスのメソッドを呼ぶようにインスペクターで設定しており、CameraControllerクラスでは実際のカメラコントロールを行っています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using StarterAssets;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class UIController : MonoBehaviour
{
    public Canvas movUICanvas;
    StarterAssetsInputs playerInput;
    CameraControllerScript cameraControllerScript;

    // Start is called before the first frame update
    void Start()
    {
        //初期はUI非表示
        movUICanvas.enabled = false;
        //ゲームオブジェクト取得
        playerInput = GameObject.Find("PlayerArmature").GetComponent<StarterAssetsInputs>();
        cameraControllerScript = GameObject.Find("CameraController").GetComponent<CameraControllerScript>();
    }

    // Update is called once per frame
    void Update() { 

    }

    //カメラボタンクリック
    public void ClickCameraButton() {
        //カメラモードに切り替え
        cameraControllerScript.PhotoModeEnable();
    }

    //カメラモード-ゲームボタン押下
    public void ClickGameButton() {
        //ゲームモードに切り替え
        cameraControllerScript.PhotoModeDisable();
    }

    public void ClickSutterButton() {
        cameraControllerScript.CameraShot();
    }
    public void ClickCameraRotateUp()
    {
        // 上を向く
        cameraControllerScript.UpRotateCamera();
    }
    public void ClickCameraRotateDown()
    {
        // 下を向く
        cameraControllerScript.DownRotateCamera();
    }
    public void ClickCameraRotateRight()
    {
        // 右を向く
        cameraControllerScript.RightRotateCamera();
    }
    public void ClickCameraRotateLeft()
    {
        // 左を向く
        cameraControllerScript.LeftRotateCamera();
    }

    public void ClickReverse() {
        //180度反転
        cameraControllerScript.reverseCamera();
    }
    public void ChangeSlider(float value)
    {
        //カメラの距離調整
        cameraControllerScript.CameraPositionChange(value);
    }
}

using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class CameraControllerScript : MonoBehaviour
{
    public GameObject mainCamera;
    public GameObject photoCamera;
    public AudioClip shutterSound;

    public GameObject mainCanvas;
    public GameObject cameraModeCanvas;

    public Image photoImg;

    private bool isPhotoMode;
    private string folderName = "Screenshots";
    private bool isCreatingScreenShot = false;
    private bool inCameraMode = true;
    private string path;
    private Canvas CameraCtr;
    private Vector3 originPosition;
    private Quaternion originRotation;

    AudioSource audioSource;

    // Start is called before the first frame update
    void Start()
    {
        audioSource = GetComponent<AudioSource>();
        mainCanvas = GameObject.Find("MainCanvas");
        cameraModeCanvas = GameObject.Find("CameraModeCanvas");
        photoImg = GameObject.Find("photoImg").GetComponent<Image>();
        CameraCtr = GameObject.Find("CameraCtr").GetComponent<Canvas>();

        //保存先のパス
        path = Application.dataPath + "/" + folderName + "/";

        //カメラ初期状態の記録
        originPosition = photoCamera.transform.position;
        originRotation = photoCamera.transform.rotation;

        // サブカメラはデフォルトで無効にしておく
        PhotoModeDisable();

        //イメージ表示部のサイズ変更
        photoImg.rectTransform.sizeDelta = new Vector2(Screen.width * 0.6f, Screen.height * 0.6f);
        //撮影画像表示部を隠す
        photoImg.enabled = false;

    }

    // Update is called once per frame
    void Update()
    {
        
    }

    //写真撮影呼び出しメソッド
    public void PrintScreen()
    {
        StartCoroutine("PrintScreenInternal");
    }

    //写真撮影のコルーチン
    IEnumerator PrintScreenInternal()
    {
        //出力中だったらキャンセル
        if (isCreatingScreenShot)
        {
            yield break;
        }

        //出力中フラグオン
        isCreatingScreenShot = true;

        yield return null;

        //フォルダがなかったら作成
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }

        //撮影日付でファイル名設定
        string date = DateTime.Now.ToString("yy-MM-dd_HH-mm-ss");
        string fileName = path + date + ".png";

        //カメラ操作部を非表示
        CameraCtr.enabled = false;

        //画像撮影
        ScreenCapture.CaptureScreenshot(fileName);

        //画像が出来上がるまで待つ
        yield return new WaitUntil(() => File.Exists(fileName));

        //画像を表示するためスプライト化
        byte[] bytes = File.ReadAllBytes(fileName);
        Texture2D texture = new Texture2D(Screen.width, Screen.height);
        texture.LoadImage(bytes);
        Sprite texture_sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);

        //2秒表示
        photoImg.enabled = true;
        photoImg.sprite = texture_sprite;

        yield return new WaitForSeconds(2f);

        //フラグリセット
        CameraCtr.enabled = true;
        photoImg.enabled = false;
        isCreatingScreenShot = false;

    }

    public void PhotoModeEnable()
    {
        isPhotoMode = true;
        inCameraMode = true;

        //カメラ初期状態の記録
        originPosition = photoCamera.transform.position;
        originRotation = photoCamera.transform.rotation;

        //UI変更
        mainCanvas.SetActive(false);
        cameraModeCanvas.SetActive(true);

        mainCamera.SetActive(false);
        photoCamera.SetActive(true);


    }
    public void PhotoModeDisable()
    {
        isPhotoMode = false;

        //スライダーリセット
        Slider slider = cameraModeCanvas.GetComponentInChildren<Slider>();
        slider.value = 0;

        //UI変更
        cameraModeCanvas.SetActive(false);
        mainCanvas.SetActive(true);

        //カメラ位置リセット
        photoCamera.transform.position = originPosition;
        photoCamera.transform.rotation = originRotation;

        //カメラ切替
        mainCamera.SetActive(true);
        photoCamera.SetActive(false);

    }
    public void CameraShot()
    {
        audioSource.PlayOneShot(shutterSound);
        PrintScreen();
    }
    public void UpRotateCamera()
    {
        photoCamera.transform.Rotate(-5, 0, 0);
    }
    public void DownRotateCamera()
    {
        photoCamera.transform.Rotate(5, 0, 0);
    }
    public void RightRotateCamera()
    {
        photoCamera.transform.Rotate(0, 5, 0);
    }
    public void LeftRotateCamera()
    {
        photoCamera.transform.Rotate(0, -5, 0);
    }
    public void reverseCamera() {
        //インカメ→外カメ
        if (inCameraMode)
        {
            photoCamera.transform.rotation = originRotation;
            photoCamera.transform.Rotate(0, 180, 0);
            inCameraMode = false;
        }
        //外カメ→インカメ
        else
        {
            photoCamera.transform.rotation = originRotation;
            inCameraMode = true;
        }

    }
    public void CameraPositionChange(float value)
    {
        photoCamera.transform.position = originPosition;
        photoCamera.transform.Translate(0, 0, value * -1);
    }

}

なんだか味気ない記事になってしまいましたが、
次回の記事でまたお会いできればうれしいです。
それでは!