てふノート

てふたろうの考えてること

【ルービックキューブ】てふメモ その参 【Unity】

おはようございます、てふたろうです。

 

 

今日はルービックキューブの進捗のほどを書いていきたいと思います。出来れば昨日書きたかった…!

 

 

製作開始して2日も経っていないのですが

現時点での進捗はこんな感じ


 f:id:tefutarou:20190322211653g:plain

 

 

 

 

 

 

 

 

もう完成してるやん、と思われるかもしれませんが課題は山ほどあります。

課題をひとつひとつ明確にして今後の方針を定めます。

 

 

これが使用してるコード、

▼基本的な動作のスクリプト
 

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

public class action : MonoBehaviour
{
    GameObject OnMouseObject;
    GameObject ClickObject;
    public GameObject parent;
    public GameObject child;
    Collider collision;
    bool a;
    bool b;
    bool c;
    public static bool only;

    Rotation Rotation;

    void Start()
    {
        Rotation = parent.GetComponent<Rotation>();
        parent.transform.DetachChildren();
        a = false;
        b = false;
        c = false;
        only = false;
    }

    public void OnMouse()
    {
        OnMouseObject = this.gameObject;
        Debug.Log(OnMouseObject + "を選択しますか?");
        c = true;
    }

    public void ExitMouse()
    {
        c = false;
    }

     void Update()
    {
        if (only==false&&c==true&&Input.GetMouseButton(0))
        {
            Debug.Log(OnMouseObject + "を選択しました。");        
            b = true;
        }
        if (Input.GetMouseButton(1))
        {
            b = false;
            a = false;
            only = false;
        }
        if (a == true)
        {
            only = true;
            Rotation.Rot();      
        }
    }


    void OnTriggerStay(Collider collision)
    {
        if (b == true)
        {
            string layerName = LayerMask.LayerToName(collision.gameObject.layer);
            if (layerName == "Cube")
            {
                child = collision.gameObject;
                child.transform.parent = parent.transform;
                a = true;
                // Debug.Log("接触");
            }
        }
        if (b == false)
        {
            parent.transform.DetachChildren();
           // Debug.Log("解除しました");
        }
    }
}

 
 

 
▼回転に関するスクリプト
 

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

public class Rotation : MonoBehaviour
{
    public void Rot()
    {
        OnRotate(new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")));
    }

    [SerializeField]
    float RotationSpeed;

    void OnRotate(Vector2 delta)
    {
        float deltaAngle = delta.magnitude * RotationSpeed;
         
        if (Mathf.Approximately(deltaAngle, 0.0f))
        {
            return;
        }

        Transform cameraTransform = Camera.main.transform;
        Vector3 deltaWorld = cameraTransform.right * delta.x + cameraTransform.up * delta.y;

       // Vector3 axisWorld = Vector3.Cross(deltaWorld, cameraTransform.forward).normalized;
        Vector3 axisWorld = transform.up;
        transform.Rotate(axisWorld, deltaAngle, Space.World);
    }
}

 

▼親のコンポーネント
 
f:id:tefutarou:20190322215330p:plain
 

 
▼子のコンポーネント 
 
 f:id:tefutarou:20190322215339p:plain
 


 
 
 

目を通すとわかるのですが、謎のbool群がいますね。これも直すべきもののひとつですね。

 


 

1.回転操作を直感的に、逆回転の実装

 

じつは今のルービックキューブでは、

1方向の回転しか出来ません。

 
f:id:tefutarou:20190322212916g:plain


 

 

これは以下の問題によるものです。

①ドラッグ操作をベクトルとして取得できない

ドラッグ操作距離を獲得することは出来たのですが、ベクトルとして記述しても正しく動作しません。

②回転の扱い方、クォータニオン

回転の記述に苦戦しています。簡単な回転から動作テストをする必要がありそう。

 

 

 

 

それと、

回転を終えたあと停止する位置が45度や135度、厳密には89度など直角でない場合に関する問題があります。

それは、キューブの位置がそれによってズレを引き起こしてしまうという問題です。

 

必要なのは、90n度への自動回転と停止のシステムです。

自然な自動回転を表現する場合、時間を要するためその間操作を無効にする記述も要求されますね。

 

 

 

 

 

2.回転する任意のオブジェクト群を選択させる

 

次に問題となるのは、回転したいオブジェクト群を選択できるシステムです。

 

現時点ではこんな感じ
f:id:tefutarou:20190322215151p:plain
 

 

見てわかるかと思われますが、ターゲットとなるコライダーが被っている面が存在します。

 

どの面からも同一の操作で選択可能にするためには全てのコライダーを同一の形状にするべきと考えたために生じた弊害です。

 

 

 

問題点を改めてあげるとすればこんな感じ

①任意のオブジェクトを選択できない(場合がある)

テストプレイの段階では、空間に設置したコライダーを半透明に表示することでなんとか選択することは可能です。

しかし、完全に透明にした場合任意に選択させることは出来るでしょうか?

 

これに付随してコライダーの大きさはどの程度が現実的なのかを調べる必要性が生じます。

 

 

②選択しているオブジェクトを目視で判断できない

これは、コライダーにポインタを重ねた際今自分が選択しているコライダーがどこのものなのかを何らかの形で表現する必要があります。

 

これに関してはシェーダーに関する知識を要求するため、より深い理解を求められるような気がしてます。

コード見ても何が何やらだったので…

 

 

 

コライダーの選択に関しては何となくヒントを得ています。

コライダー全体を囲むよう周囲にコライダーを設置して条件分岐させてみたり、

 

キューブとキューブが接触する辺の中央あたりにひとつコライダーだけが選択できる空間があるのでこれを利用してみたりです。

 

 

 

3.ゲーム性とオリジナリティ

 

これに取りかかれたらどんだけ楽しいか。

 

ゲーム性を持たせること自体は難しくはありせん。

現時点でキューブの面をキューブとは別のオブジェクトとして構成しているため

 

コライダーの接触で検知したり、

Rayを飛ばして判別したり、

すれば面が揃っているという判断は出来るでしょう。

 

 

しかし、面をランダムに設置。何度か回転させた状態からスタート。といったシステムの記述に関してヒントを得られていないのも事実。

 

ルービックキューブアルゴリズムをもう少し調べなくては…

 

 

 

 

そんでオリジナリティについて。

 

オリジナリティを付けるとすれば、

 

スロット画面をルービックキューブ状に割って、結果をルービックキューブで改変できるとか。

 

勇者、魔王、姫、モンスターの面を作って、接触させることで先頭するとか。

 



 

わりと面白い発想は浮かんでますね。

 

 

 

今日の進捗紹介はここまで。

なんとか完成させたいものです、

 

 

 

 

4.あとがき

 

昨日Github始めました。

まだ使い方がいまいち掴めてないんですよね。

Macならやりやすかったのかな