もねスタ

Unity、Blender、Aflame中心にVR/ARなど好き勝手書いていく雑記ブログ

【Unity】エラー「Unexpected symbol `***’ in class, struct, or interface member declaration」を解説

f:id:saharu54:20181110154946p:plain
最近Aframeの話題ばかりでしたがUnityに戻ってきました。

近頃ARkitの教科書を見ながらいくつかARのデモ開発していたのですが、こんなエラーに遭遇しました。

エラー:
Unexpected symbol `ParticleSystem’ in class, struct, or interface member declaration

このように
Unexpected symbol `hogehoge’ in class, struct, or interface member declaration と表示される場合は大抵タイプミスです。

今回はエラーが出た該当の行ではなく上の行で" ; "が抜けていました

例:

public class ParticleSystemScript : MonoBehaviour {

    GameObject obj;
    GameObject obj2;
    GameObject obj3

    ParticleSystem ps;
    ParticleSystem ps2;
    ParticleSystem ps3;

    // Use this for initialization
    void Start () {

今回エラーが出たのは「Unexpected symbol `ParticleSystem’ in class, struct, or interface member declaration」でしたが
ParticleSystemの部分、特に悪いところは無さそうです。

上を見てみると
GameObject型の変数obj3を宣言した後の” ; “が抜けていました

今回はここを訂正したらエラーが消えました。

【aframe】ランダム(position, rotation, scale, color)にオブジェクトを配置する【randomizer】

f:id:saharu54:20181025030321p:plain
画像引用:https://ngokevin.github.io/kframe/components/randomizer/examples/basic/

こちらの記事ではaframeにてランダムの値を適用してくれるライブラリを紹介します。

randomizerコンポーネント使い方

githubはこちら

github.com

以下がサンプルコードです。

<head>
  <title>My A-Frame Scene</title>
  <script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
  <script src="https://unpkg.com/aframe-randomizer-components@^3.0.1/dist/aframe-randomizer-components.min.js"></script>
</head>

<body>
  <a-scene>
    <a-entity geometry="primitive: box"
              random-position random-rotation random-scale></a-entity>
  </a-scene>
</body>

上のサンプルコードではposition, rotation, scaleが全てランダム。
あとなんとcolorもランダムにできました。

それでは応用して色々いじってみましょう。

範囲を指定する

例えばposition="-5 -5 -5"から"5 5 5"の間に表示させるように範囲を指定してみます。

<a-entity geometry="primitive: box" random-position="min: -5 -5 -5; max: 5 5 5" random-rotation scale="1 1 1"></a-entity>

このようにすれば"min: -5 -5 -5; max: 5 5 5"の間でランダムな位置に自動生成されます。

他のオブジェクトや3Dモデルに変更する

もちろんですが、box以外のいろんなオブジェクトにも適用できます。

<a-entity geometry="primitive: sphere" random-position="min: -5 -5 -5; max: 5 5 5" random-rotation scale="1 1 1"></a-entity>

3Dモデルを表示させたいときは、まず大前提としてこんな風にa-asset内で呼び出しておいて

<body>
  <a-assets>
    <a-asset-item id="3dmodel-obj" src="model.obj"></a-asset-item>
    <a-asset-item id="3dmodel-mtl" src="model.mtl"></a-asset-item>
  </a-assets>

  <a-scene>
  </a-scene>
</body>

a-scene内でこんな感じ

  <a-scene>
    <a-entity random-position="min: -5 -5 -5; max: 5 5 5" random-rotation scale="1 1 1">
      <a-obj-model src="#3dmodel-obj" mtl="#3dmodel-mtl"></a-obj-model>
      <!-- アニメーションなどもここに -->
    </a-entity>
  </a-scene>

応用してこんな感じのものが作れました

f:id:saharu54:20181025034915p:plain

こちらはカーソルを合わせて数秒待つとオブジェクトが消える簡単なシューティングゲームですが
今回のrandomizerコンポーネントを利用してpositionを
random-position="min: -9 1 -6; max: 9 5 -10"として、常にプレイヤーの前面にランダムに出現するようにしてみました。

シューティングなんかはランダム配置した方が、ロードするたびに新鮮でより良いですよね。

【TGS2018】東京ゲームショウ2018レポート!VRブース中心!

f:id:saharu54:20180922162951j:plain TGS楽しかった〜〜!!っていうレポです。
熱中しすぎて写真あんまりないです…ごめんなさい

はじめに

まず簡単に、わたしの目的と見たブースを書いておきます。

  • VR開発ちょびっとやってるので主な目的はVRブース
  • twitterで気になってた「KARATE URANAI」見たい
  • 混雑すごかったため大手企業の新作ゲームブースはすっ飛ばした
  • インディーズゲームブース見たい

こんな感じで行ってまいりました。
それではレポートどうぞ!

KARATE URANAI

youtu.be

まず真っ先に向かったのはKARATE URANAI!!
「KARATE URANAI」とはインディーズでゲームを開発されているksymさんのゲームのこと。

▼ksymさんTwitter twitter.com

このゲームのことはTwitterで事前に見ていて、その可愛らしいビジュアルと謎の多い内容からとても興味があったんです。

どうやって遊ぶのかな?って思ってチャレンジしてきましたが
結局どうやって遊ぶのかはわかりませんでした。

端的にいうとゲームでもなくて(?)占いなので吉とか凶とか運勢が出てきます。

わたしの順番が来るとゲームの説明を始めてくれたksymさん
わたし「…あれ、これってゲームもう始まってます?」
ksymさん「始まってます」

どうやらこのゲームにはスタートという概念が無いようです。

しかもこの後、まだ説明を聞いている最中に大吉が出てしまい、操作せずに景品のUSBまで頂くという展開になりました。
わたしにも未だ何が起こったのか分かりません。 f:id:saharu54:20180922165320j:plain 画像:なんかチェキまで撮ってもらってプレゼントしてもらうという至れり尽くせりのブース

そんなKARATE URANAIですが、操作はなんと「礼」と「アボカドを投げる」の二つだけ。

わたし「なるほど、二つの操作だけなんですね。 これ二人キャラクターがいますけど、どっちがプレイヤーですか?」
ksymさん「プレイヤーとかそういうのありません。」

ksymさん「あと、この黄色いトラがうんちしますので…」
わたし「トラ?」

f:id:saharu54:20180922163359p:plain 画像引用:KARATE URANAI - YouTube
画像右下のミニマルな生き物を「トラ」と主張するksym氏

会話からお分かりいただけるように、開発者のksymさんも謎の多い楽しい方でした。
結局KARATE URANAIとはなんだったのか?謎は解けませんでしたがksymさんへの信頼だけは確かなものとなりました。

VR体験

その後VRブースへ移動して簡単に見て回りました。
一通り回って話聞いたりしたんですが、わたしが実際に体験できたのはこちら

VR歩行デバイスとかVRサイクルデバイスとか強そうなデバイスやってみたかったんですが、こちらはすでに整理券配布終了で体験できませんでした。

しかしVRゲームは触れば触るほど気づきがたくさんありますね…。

例えば、何を目的として作られているのかがイマイチ分からないゲームは興味をそそられないし(KARATE URANAIを除く)、
「とりあえずVRコンテンツ作ってみた」的な感じのものか、「これが作りたい」って能動的に作ったものかってすぐに伝わるなぁとか
あと実際の仕様の面だと、音楽とゲーム体験の一致って結構難しくてシビアで違和感がこうも簡単に生まれてしまうのかとか…
あとデザインやUI、操作性も色々と見れて勉強になりました。

インディーズゲーム

最後はフラフラとインディーズゲームのブースを見て回りました。
特にどういうゲームデザインがあるのかなってとこと、世界観をどう操作性に結びつけてるのかなってとこ見てきました。

「世界観を操作に結びつける」

「世界観を操作に結びつける」ってなんじゃいっていうのは、
わたし自身「こういうストーリーのゲーム作りたいなぁ」っていう世界観が先にあって、じゃあRPGにするのか、ノベルゲーなのか、アクションなのかってとこに結びつけるのが難しいと感じるからです。

世界観を作る頭はあるけど、そこにゲーム体験を違和感なくくっつける知見がない。
そのためその辺重点的に見たいなぁと思ってました。

さて、それについて今回思ったのはいろんなゲームのかたちがあるということ。

各自自分のデバイスでワールド作ってSNSで共有してねって放置型だってあるし、選択肢なしにただ読み進めるだけのノベルもある。
自分の世界観を崩さず、かつインタラクティブにする方法を新たに開拓してもいいのかもねって思いました。

とにかくいろんなゲームがある

びっくりしました。本当にいろんなデザイン、いろんなデバイスを使った、いろんなゲームがある。

やり尽くされてない分野ってあるのかな?って感じですけど、逆に自分の作りたいもの作ろうかなって勇気付けられました。
今回体験させてもらったブースの方々ありがとうございました!!

おわりに

実は去年、お手伝いとして出展者側でTGSに参加していました。
でも去年はゲームやVRなんて興味なかったんですよね。
それが一年経って、VR界隈にいて、そしてまたこのTGSに戻ってこられたことが嬉しいです。

今度はインディーズゲームとかリリースして、出展者側としてまた戻ってこられたら楽しいだろうなぁ。
制作がんばります。

【Unity C#】基本!シンプルな移動・回転スクリプトを解剖する

f:id:saharu54:20180917174029g:plain
こんにちは。
最近はaframeばかり触っていましたがUnityにちょこっと帰って来ました。

今回も非エンジニアの著者が勉強と自分用のメモを書いていきたいと思います。
(コーディング勉強中の身なので参考程度にご覧ください)

今回の勉強するポイントは
C#でシンプルな移動・回転を実現するにはどのようにすればいいか。
アニメーションの呼び出しなどはしません。

前置き

今回は私が一番よく利用するCharacterControllerを利用した移動方法です。

コードなどに関してこちらの記事を参考にさせていただきました。 tama-lab.net

さっそくコード

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

public class controller : MonoBehaviour {

  // まずspeed、gravityの数値を代入
    public float speed = 3.0f;
    public float gravity = 20.0f;
     
    private Vector3 moveDirection = Vector3.zero;
    
    void Update () {
        
        // CharacterController取得
        CharacterController controller = GetComponent<CharacterController>();

        // 回転
        transform.Rotate(0, Input.GetAxis("Horizontal") * speed, 0);


        if (controller.isGrounded) {
            moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
            moveDirection = transform.TransformDirection(moveDirection);
            moveDirection *= speed;
            
        }
        moveDirection.y -= gravity * Time.deltaTime;
        controller.Move(moveDirection * Time.deltaTime);
    }
}

コーディング勉強中の身としては、
何がなんの挙動をしているのかが一番知りたいポイントなので自分なりに分解していきます。

移動スクリプトで最低限必要なものは何か

① まず移動ということで移動スピードと重力の指定は必須
なので最初にspeedとgravityに数値を代入しています。

今回回転も実装したスクリプトですが旋回スピードを変更したい場合は ここで一緒に旋回スピードを代入するといいかもですね。
Unity-chanのアセットに入っているUnitychanController.csなんかはrotateSpeedに数値入れていじれるようになっています。

特にVRFPSゲームの場合、旋回スピードが早すぎると異常に酔うので指定は必須かもしれません。

② 次にprivate Vector3 moveDirection = Vector3.zero;
正直最近コード書き始めた自分にとっては「なんのこっちゃ」って感じですが

そもそもVector3とは…

3D ベクトルと位置の表現 この構造体は Unity 全体の 3D での位置や方向のために使用されています。 一般的なベクトル演算を行うための関数が含まれています。 引用:Unity - スクリプトリファレンス: Vector3

スクリプト書いているとVector3(0, 0, 0)などの表記をよく見かけますが
これは3Dベクトル(三次元)上でx,y,z軸のどこ座標にオブジェクトがいるか、位置を示すものとしてUnityでは頻出ですね。

さて、そんな中でもVector3.zeroはVector3(0, 0, 0)と同じ意味です。

ということでprivate Vector3 moveDirection = Vector3.zero;は ゼロの座標をスクリプト内で簡単にいじれるように最初で代入しているのかな・・?(あんまりわかってない)

③ 次はvoid Updateのカッコ内を見ていきましょうかね。
回転はtransform.Rotate(0, Input.GetAxis("Horizontal") * speed, 0);で実装しています。

transformはこのお馴染みの欄にあるPosition, Rotate, Scaleをスクリプト上で変化させるときに使います。

f:id:saharu54:20180917170204p:plain

Input.GetAxis("Horizontal")についてはこちらの記事が勉強になりました

qiita.com

【aframe】エモい空つくろう!空の色を変更・グラデーションにする方法

f:id:saharu54:20180902162704p:plain

さて、今回学ぶことはこちら

  • 空の色の変更方法(単色)
  • 空をグラデーションにする方法

空の色の変更方法(単色)

f:id:saharu54:20180902163105p:plain
まずは空の色を変更する方法です。

<a-sky color="black"></a-sky>

これをa-sceneの中に入れましょう。
終わった!一瞬!!

"black"の部分に色名かカラーコードを入れてください。
ちなみに上の画像は"lightblue"を入れました。
お好みの色名やカラーコードを入れてくださいね。

空をグラデーションにする方法

f:id:saharu54:20180902163307p:plain

空をグラデーションにするにはこちら。

<head>
  <title>Page Title</title>

  <!-- aframeのライブラリ呼び出し -->
  <script src="https://rawgit.com/aframevr/aframe/master/dist/aframe-master.min.js"></script>

  <!-- 空のグラデーションのためのコンポーネント呼び出し -->
  <script src="https://unpkg.com/aframe-environment-component@1.0.0/dist/aframe-environment-component.min.js"></script>

</head>

<body>
  <a-scene>
  <a-sky radius="200" theta-length="110" material="shader:gradientshader;topColor:black;bottomColor:white" geometry="" visible="" id="sky" position=""></a-sky>
  </a-scene>
</body>

skyをグラデーションにできるコンポーネントを追加しています。
https://github.com/supermedium/aframe-environment-component

a-skyの中の"shader:gradientshader;topColor:black;bottomColor:white"
ここでtopColor(天井側の色)とbottomColor(地面側の色)を指定してあげるといい感じのグラデーションな空が完成します。

あと、radius="200" theta-length="110"
ふたつの色の割合とか変更できると思います!(まだ試してない)

上のサンプルで指定したtopColor:black;bottomColor:whiteで実行した空はこんな感じ。
f:id:saharu54:20180902164622p:plain

おまけ

f:id:saharu54:20180902165032p:plain
引用:uiGradients - Beautiful colored gradients

グラデーションの空をいい感じに作り上げるためにこんなサイトを利用してみてはいかがでしょうか!
カラーの組み合わせがとても参考になります。

uigradients.com


エモい空を作りましょう!

【aframe】インスペクターの使い方・ショートカット一覧

f:id:saharu54:20180902064257p:plain

aframeを覚えておく上で押さえておきたいインスペクターの使い方とショートカットキーをまとめました!

aframeのインスペクター機能 

aframeのインスペクターとはGUIで空間の編集ができる機能。

まずはaframeで作られたwebVRの画面で、騙されたと思って【Ctrl + Alt + i】を押してみましょう。
公式サイトのサンプルで試してみるとわかりやすいかも

f:id:saharu54:20180830002820p:plain
引用:https://aframe.io/examples/showcase/helloworld/

こんな感じの画面になったでしょうか
これがaframeのインスペクターと呼ばれる編集画面。

左側のなどの欄でこのページにどんな要素が含まれているか確認できますし、左上のピンクの「Back to Scene」を押せば元のwebVRに戻れます。

aframeを利用したウェブサイトならこのインスペクターで要素の構成なんかが簡単に確認できちゃいます。
「Back to Scene」ボタンの下のアイコンでhtmlファイルとしてPCにコードを落とすこともできます。
「このwebVRどうやって動いてんの?」って思った時はインスペクター見て挙動や構成など参考にするのがオススメです。

英語ですが、公式の使い方ガイドはこちら。
Visual Inspector & Dev Tools – A-Frame


ショートカットキー一覧

わかる限りまとめてみたショートカットキーはこちら。
参考になるのかは謎

<基本機能>
W …移動カーソル
E …回転カーソル
R… スケールカーソル

<その他>
G …地面のグリッド表示/非表示
F …オブジェクトを選択していると拡大
N …中心点選択

【A-Frame】A-Frameとは?インスペクター、視点カーソルの追加方法まとめ

f:id:saharu54:20180829235848p:plain
引用:https://aframe.io/examples/showcase/helloworld/
「A-FRAME」とはWebVRを実現するフレームワークです。
個人的な魅力は何と言ってもWebVRが、スマホでも楽しめるということ。

UnityでwebGLでビルドしてもスマホからサクサク見られないですからね…
誰でも、どんなデバイスでも楽しめるという点でVRをより身近にしているのがaframeです。だいすき。
開発方法もhtmlタグでできるので初心者にとってとっつきやすいのが特徴。

今回はそんなA-Frameで視点カーソルの追加方法をご紹介します。
※コーディング勉強中の身のため、ゆるめにご覧ください

視点カーソルの追加

WebVRって見るだけでも楽しいですが、操作性あるとより魅力が増しますよね。
WebVRに操作性をプラスするには視点カーソルを追加してみてはいかがでしょうか。

先人のエンジニアの皆様のブログなど拝見していると、視点カーソルってバリエーション結構たくさんあるようです。

スタンダードなのはこんな感じ (真ん中の灰色の丸)

f:id:saharu54:20180830000405p:plain

こちらはシンプルな円のカーソル。
このカーソルをオブジェクトに合わせるとカーソルが縮小して、縮小しきったらリンクに飛ぶという仕様なんかもできます。 

このカーソルのコードはこんな感じ

<!-- カーソルを作る -->
    <a-camera position="0 0 0">
      <a-entity cursor="fuse: true; fuseTimeout: 2000" position="0 0 -1" geometry="primitive: ring" scale="0.03 0.03 0.03" material="color: gray; shader: flat">
        <a-animation begin="cursor-fusing" easing="ease-in" attribute="scale" fill="none" from="0.03 0.03 0.03" to="0.001 0.001 0.001">
        </a-animation>
      </a-entity>
    </a-camera>

メインのhtmlではこのようにカーソルの大きさや形、アニメーションなどを指定しておいて
実際のリンクなどの挙動は別のjsファイルで指定しています。

cursor.jsというjsファイルを呼び出すhtml

<script src="./cursor.js"></script>

jsファイルはこんな感じ

  var boxEl = document.querySelector('#right1');
  // カーソルがぶつかったら拡大
  boxEl.addEventListener('mouseenter', function () {
    boxEl.setAttribute('width', 10);
    console.log("mouseenter");
  });

  // カーソルが離れたら元にもどす
  boxEl.addEventListener('mouseleave', function () {
    boxEl.setAttribute('width', 3);
    console.log("mouseleave");
  });

  let strat = false;

  document.querySelector('#right1').addEventListener('click', function (evt) {
    start = true;
    if (start) {
      location.href = "https://google.com";
    }
  });

 
jsファイルの下の方にあるここの部分

 document.querySelector('#right1').addEventListener('click', function (evt) {
    start = true;
    if (start) {
      location.href = "https://google.com";
    }
  });

こちらでは、index.htmlの方でオブジェクトにIDをつけておいてそのIDに応じてリンク先を指定するということをやっています。 

document.querySelector('#ID名')
location.href = "リンク先のURL"
という感じ。


参考サイト

視点カーソルを作るにおいて参考にさせていただきました。
https://keeponrockin.hatenablog.com/entry/2016/11/10/004137keeponrockin.hatenablog.com

視点カーソルのみならず、aframe触る上で参考になるサイトさま

roman-tech.hatenablog.jp

bashalog.c-brains.jp