---
# System prepended metadata

title: Day 18 | FPS滅火AR遊戲開發Part3 - 火焰生成
tags: [Unity, AR手遊]

---

# Day 18 | FPS滅火AR遊戲開發Part3 - 火焰生成 
###### tags: `Unity` `AR手遊`

昨天的文章中已介紹火焰粒子的製作，那麼今天的文章將會說明如何在AR世界中產生火焰！

## 火焰產生器
在場景中，創建一個Empty GameObject，添加新的火焰產生器script，宣告物件變數，放入上一篇文章製作的火焰Prefab。

```
public Gameobject FlamePrefab;    
```
遊戲機制為計時到固定時間後，產生火焰，在限時內滅火一定數量即可通關。主要的框架如下:
```
void Update()
{
    if(產生 == true){
    
         Fire();//產生火焰function;

    }else{
 
        nextFireTime();計時下一次產生火焰funtion;

    }
}
```
因為產生器的機制與計時有關，所以放在Update()函式當中。

### 火焰產生器計時，時間一到就升火 nextFireTime()

在產生器的class當中宣告計時變數。
```
privae float generateTime = 0f;    
```

在計時的函式nextFireTime()中，如果計時超過了2.5秒，就呼叫產生函式Fire()，產生一朱火焰;如果還沒到產生時間，就讓generateTime持續增加Time.deltaTime，繼續計時。

```
nextFireTime()
{
    if(generateTime>2.5f)
    {
    
        Fire();  //產生火焰
    
    }else{
        
        generateTime += Time.deltaTime;
    
    }
}
```



### 隨機地點生成

在Fire()函式當中，產生火焰之前要先隨機選擇要產生的點:
* 宣告int變數，儲存使用Random.Range函式生成的數值
* 宣告Vector2變數，用來儲存之後要產生的Position
* 利用switch選擇Position
* 使用ViewportToScreenPoint
  * Viewport:相對於相機是標準化的。相機的左下角是 (0,0)；右上角是 (1,1); z 位置以相機的世界單位為單位。
  * ScreenPoint:以像素為單位定義。屏幕左下角是(0,0)；右上角是（pixelWidth , pixelHeight）。z 位置以相機的世界單位為單位。
* 生成的火焰希望分別是三個位置，固定的y值。

```
int Randomnum;
Vector2 screenPosition;

Randomnum = Random.Range(0, 3);
switch (Ramdonnum)
{
    case 0:
    screenPosition = Camera.main.ViewportToScreenPoint(new Vector2(0.25f, 0.4f));
        break;
    case 1:
    screenPosition = Camera.main.ViewportToScreenPoint(new Vector2(0.5f, 0.4f));
        break;
    case 2:
    screenPosition = Camera.main.ViewportToScreenPoint(new Vector2(0.75f, 0.4f));
        break;
                }
```


### 射線、平面管理器
* 在ARSessionOrigin中掛上AR PlaneManager及AR RaycaseManager兩個元件
* 將AR Default Plane製成Prefab，放入AR PlaneManager的Plane Prefab中(不喜歡預設的Plane可以針對Mesh的部分做更改)

![](https://i.imgur.com/cJsoqdz.png)

### 射線、平面碰撞

在產生器的class當中宣告ARRaycastManager，在Unity將ARSessionOrigin放入。

```
public ARRaycastManager raycastManager;
```
* 宣告撞擊List，儲存射線撞擊物體的訊息。
* 使用Raycast，從螢幕座標的一個點向可追蹤類型投射光線。
* 如果有撞擊發生，取得撞擊的第一個位置作為產生火焰的位置。

```
List<ARRaycastHit> hits = new List<ARRaycastHit>();
raycastManager.Raycast(screenPosition, hits, UnityEngine.XR.ARSubsystems.TrackableType.Planes);
if (hits.Count > 0)
{
    GameObject.Instantiate(FlamePrefab, hits[0].pose.position, hits[0].pose.rotation);
}
```



---


今天的文章利用 Raycasy Hit搭配Plane偵測，順利的讓火焰在AR世界中產生了，下一篇就會撰寫滅火的部分，那就明天見~




