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();
}
}
}
}
}
}