LoginSignup
1
5

More than 3 years have passed since last update.

Unityでピンボールのフリッパーを作る

Last updated at Posted at 2019-12-23

はじめに

この記事は SLP KBIT Advent Calendar 2019 の21日目の記事です。
SLP KBIT Advent Calendar 2019

概要

ピンボールが作りたくなったので、Unityで実装していきたいと思いました。
中でも今回はピンボールのボールをはじく部分をHingeJointを用いてつくっていきます。

実行環境

Unity version:2019.2.9f1

参考URL

スクリプトリファレンス
Hinge Jointでシーソーを作る
【Unity】 重力を変更する

事前準備

scene上に3Dオブジェクトを置きます。

名前 3D Object
Floor Cube
Ball Sphere
AxisL, R Cylinder
FlipperL, R Cube

このように配置しました。
image1.png

HingeJoint

ヒンジとはドアの接合部に使われているような回転の支点となる部分の事だそうです。
UnityではHingeJointがついている物体をヒンジで接合されているように動かすことができるようです。
今回はHingeJointの中でもSpringという変数をつかってばねの力でボールを弾こうと思います。

使ってみます

まずHingeJointComponentを軸になるオブジェクトに加えます。
軸には重力がかかってほしくないのでUseGravityのチェックを外し、
物理の影響を受けてほしくないのでIs Kinematicのチェックをつけます。
ここではAxisRにAdd Componentしています。
スクリーンショット (8).png

HingeJointは2つのRigidbody(剛体)をつなげるので動かす部分にRigidbodyを加えます。
ここではFlipperRにAdd Componentしています
スクリーンショット (7).png

2つのRigidbodyをHingeJointで繋げるために、
AxisRのHingeJoint内のConenected BodyにFlipperRをドラッグアンドドロップします。

これをAxisLとFlipperLにも行います。

この後AxisRのHingeJointのEdit Joint Angular LimitsでHingeの向きと方向を編集します。
Axisの値で調整します。
矢印を軸として、円に沿って力が加わるので上向きにします。(反時計回りが正)

変更前
スクリーンショット (9).png
変更後
スクリーンショット (10).png
この時点でAxisRのHingeJointの
UseSpringにチェックを入れ、Springに40000、Damperに0、TargeetPositionを-60にすると
スクリーンショット (11).png
このようになりました。(AxisLも変更済み)

この時にフリッパーが回転しすぎたりしないようにAxisRのHingeJoint内のUse Limitsにチェックを入れ、
Minに-60、Maxに0を入れます。(AxisLも同様)

この後、左クリックで左フリッパー、右クリックで右フリッパーを動かしてみます。

コード

Flipper.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Flipper : MonoBehaviour
{
    // Inspecterで値を変更する
    public float spring = 40000;
    public float openAngle = 60; // 開く角度
    public float closeAngle = 0; // 閉じる角度

    // Hinge Joint
    private HingeJoint hjL; // AxisL
    private HingeJoint hjR; // AxisR

    // JointSpring
    private JointSpring jL; // AxisL
    private JointSpring jR; // AxisR

    void Start()
    {
        // AxisLとAxisRを探す
        GameObject flipperL = GameObject.Find("AxisL");
        GameObject flipperR = GameObject.Find("AxisR");

        // HingeJointを受け取る
        hjL = flipperL.GetComponent<HingeJoint>();
        hjR = flipperR.GetComponent<HingeJoint>();

        // Springを受け取る
        jL = hjL.spring;
        jR = hjR.spring;
    }

    void Update()
    {
        // 左クリックを押す
        if (Input.GetMouseButtonDown(0))
        {
            jL.spring = spring;
            jL.targetPosition = openAngle;
            hjL.spring = jL;

        }
        // 左クリックを離す
        if (Input.GetMouseButtonUp(0))
        {
            jL.spring = spring;
            jL.targetPosition = closeAngle;
            hjL.spring = jL;
        }
        // 右クリックを押す
        if (Input.GetMouseButtonDown(1))
        {
            jR.spring = spring;
            jR.targetPosition = -openAngle;
            hjR.spring = jR;
        }
        // 右クリックを離す
        if (Input.GetMouseButtonUp(1))
        {
            jR.spring = spring;
            jR.targetPosition = closeAngle;
            hjR.spring = jR;
        }
    }   
}

Update関数内でボタンを検知しています。
左クリックをすると40000の力で60度左フリッパーが回転、
右クリックをすると40000の力で-60度右クリックが回転します。

実行結果

Edit→Project Settings→PhysicsでGravityの方向を変更します。
フリッパーが重力の影響を受けないようにFlipperL、FlipperRのUseGravityのチェックを外しました。
重力を反映させるためBallにRigidbodyをつけます。
実行するとこんな感じになりました。
gifanime-compressor.gif

カクついていますが何とか動いています。

終わりに

結構ちゃんとフリッパーしてくれていると感じました。
ピンボールはフリッパーだけではできないので他の部分も実装してみたいと思いました。

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5