Unity (AR Foundation, AR Kit) - もぐらたたきARを作りました(2021/3/27)

念願のもぐらたたきARに挑戦です。次の記事を参考にしました。

開発環境

Unity 2020.1.6f
AR Foundation 3.1.6
ARKit 3.1.8
ARCore 3.1.8

AR FoundationとAR Kitの設定、もぐらの穴表示まではこれを参考

なんとかうごいたので!最終のコードを載せておきます。

MoleController.cs

(MoleController.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class MoleController : MonoBehaviour
{
   Vector3 groundLevel;
   Vector3 undergroundLevel;
   public GameObject effect;

   bool isOnGround = true;
   float time = 0;
   // Start is called before the first frame update
   void Up()
   {
       transform.DOMoveY(groundLevel.y, 0.5f);
       this.isOnGround = true;
   }

   void Down()
   {
       transform.DOMoveY(undergroundLevel.y, 0.5f);
       this.isOnGround = false;
   }

   void Start()
   {
       this.groundLevel = transform.position;
       this.undergroundLevel = this.groundLevel - new Vector3(0, 0.2f, 0);

       // 地中に隠す
       Down();
   }


   // Update is called once per frame
   void Update()
   {
       this.time += Time.deltaTime;

       if (this.time > 2.0f)
       {
           this.time = 0;
           if (this.isOnGround)
           {
               Down();
           }
           else
           {
               Up();
           }
       }
   }
   public void Hit()
   {
       GameObject g = Instantiate(effect, transform.position + new Vector3(0, 0.04f, 0), effect.transform.rotation);
       Destroy(g, 1.0f);

       this.time = 0;
       Down();
   }

}

HolePlacer.cs

(HolePlacer.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class HolePlacer : MonoBehaviour
{
   public GameObject arHolesToSpawn;
   public GameObject molePrefab;
   public GameObject placementIndicator;

   private GameObject spawnedHoles;
   private Pose PlacementPose;
   private ARRaycastManager arRaycastManager;
   private bool placementPoseIsValid = false;

   // Start is called before the first frame update
   void Start()
   {
       arRaycastManager = FindObjectOfType<ARRaycastManager>();
   }

   //Generate Moles
   public void GenerateMoles(GameObject holes)
   {
       foreach (Transform t in holes.transform)
       {
           GameObject child = t.gameObject;
           if (child.tag == "Hole")
           {
               Vector3 pos = child.transform.position;
               GameObject mole = Instantiate(molePrefab, pos, molePrefab.transform.rotation);

               //モグラをカメラの方向に向かせる
               mole.transform.LookAt(Camera.main.transform.position);
               Vector3 mole_ang = mole.transform.localEulerAngles;
               mole_ang.x = 0.0f;
               mole.transform.localEulerAngles = mole_ang;

           }
       }
   }

   // Update placement indicator, placement pose and spawn
   void Update()
   {
       if (spawnedHoles == null && placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
       {
           ARPlaceObject();

       }
       UpdatePlacementPose();
       UpdatePlacementIndicator();
   }

   void UpdatePlacementIndicator()
   {
       if (spawnedHoles == null && placementPoseIsValid)
       {
           placementIndicator.SetActive(true);
           placementIndicator.transform.SetPositionAndRotation(PlacementPose.position, PlacementPose.rotation);
       }
       else
       {
           placementIndicator.SetActive(false);
       }
   }

   void UpdatePlacementPose()
   {
       var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
       var hits = new List<ARRaycastHit>();
       arRaycastManager.Raycast(screenCenter, hits, TrackableType.Planes);

       placementPoseIsValid = hits.Count > 0;
       if (placementPoseIsValid)
       {
           PlacementPose = hits[0].pose;
       }
   }

   void ARPlaceObject()
   {
       spawnedHoles = Instantiate(arHolesToSpawn, PlacementPose.position, PlacementPose.rotation);

       //モグラを生成する
       GenerateMoles(spawnedHoles);
   }
}

Hammer.cs

(Hammer.cs)

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

public class Hammer : MonoBehaviour
{
   int count = 0;
   void Update()
   {
       if (Input.touchCount > 0)
       {
           Touch touch = Input.GetTouch(0);
           if (touch.phase == TouchPhase.Began)
           {
               Ray ray = Camera.main.ScreenPointToRay(touch.position);
               RaycastHit hit = new RaycastHit();
               if (Physics.Raycast(ray, out hit))
               {
                   if (hit.transform.gameObject.CompareTag("Mole"))
                   {
                       hit.transform.gameObject.GetComponent<MoleController>().Hit();

                       count++;

                       GameObject.Find("Score").GetComponent<Text>().text
                           = "Score: " + count.ToString();
                   }
               }
           }
       }
   }
}