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

public class ObjectPool : MonoBehaviour
{
    [Tooltip("Copied object")]
    public GameObject copiedObject;

    [Tooltip("Parent transform. ")]
    public Transform parentTransformOrNull;

    [Tooltip("Object count")]
    public int count = 1; // default count is 1

    [Tooltip("Life time. if lifeTime is 0, it is not turn off.")]
    public float lifeTime;    // life time. if lifeTime is 0, it is not turn off.

    private GameObject[] objects;
    private int currentIdx;


    private void Start()
    {
        InitObject();
    }

    /// <summary>
    /// Use Object
    /// </summary>
    /// <param name="position">Position to create.</param>
    public void UseObject(Vector3 position)
    {
        currentIdx %= count;
        if(!objects[currentIdx].activeSelf)
        {
            objects[currentIdx].SetActive(true);
            objects[currentIdx].transform.position = position;

            StartCoroutine(IStartLifeTime(objects[currentIdx]));
            ++currentIdx;
        }
    }

    /// <summary>
    /// Init Setting
    /// </summary>
    private void InitObject()
    {
        if(count <= 0)
        {
            count = 1; // init count
        }
        objects = new GameObject[count];
        for (int i = 0; i < count; i++)
        {
            if(copiedObject == null)
            {
                Debug.LogError("Copie object not set");
            }
            GameObject obj = Instantiate(copiedObject, transform.position, Quaternion.identity, parentTransformOrNull) as GameObject;
            if (obj)
            {
                objects[i] = obj;
                Debug.Log("넣어졌다.");
            }
        }
        currentIdx = 0;
    }

    /// <summary>
    /// object life time
    /// </summary>
    /// <param name="obj">Target object to turn off</param>
    /// <returns></returns>
    private IEnumerator IStartLifeTime(GameObject obj)
    {
        if(lifeTime > 0)
        {
            yield return new WaitForSeconds(lifeTime);
            obj.SetActive(false);
        }
    }
}

참고 링크입니다.

https://docs.unity3d.com/kr/2018.4/Manual/AssetBundles-Browser.html

 

Unity 에셋 번들 브라우저 툴 - Unity 매뉴얼

참고: 이 툴은 Unity의 기본 기능이 아닌 추가 기능입니다. Unity 에디터를 다운로드하고 설치했더라도, 툴에 액세스하려면 GitHub에서 다운로드 받은 이후 따로 설치해야 됩니다.

docs.unity3d.com

 

2019.1.9f1로 합니다.

유니티 프로젝트를 켜서 유니티에 박스 3개를 프리펩스로 만들어 줍니다.

 

 

https://github.com/Unity-Technologies/AssetBundles-Browser

 

Unity-Technologies/AssetBundles-Browser

Editor tool for viewing and debugging asset bundle contents before and after builds - Unity-Technologies/AssetBundles-Browser

github.com

github 사이트로 갑니다. zip파일로 다운로드 합니다.

 

압축 푼 폴더 자체를 드래그해서 Assets 폴더에 집어넣습니다.

 

Project뷰에 프리펩스로 만든  모든 박스 오브젝트를 잡고 AssetBundle을 만들어 줍니다. 저는 "MyAsset"으로 만듬.

AssetBundles 폴더를 하나 만듭니다.

Window -> AssetBundle Browser를 누릅니다.

 

AssetBundles창이 뜨면 Inspect -> AddFile을 눌러서 만들어 두었던 박스 프리펩스 3개를 선택 하여 추가합니다. (하나씩 선택 되네요)

잘 추가가 되었습니다. 

Build로 들어가 Copy to StreamingAssets에 체크하고 OutputPath를 AssetBundles 폴더(새로 생성함)로 설정하고 Build버튼을 누릅니다.

 

(2019.3.0f6버전으로 2020년 04월 07일에 다시 실험해봤는데 Inspect에서 추가 후 빌드하면 안됩니다. Configure에서 왼쪽 창에 번들 리스트창에 하나 생성 후 Asset List에 프리펩스등를 넣은 후 Build 버튼을 누르면 빌드가 됩니다.)

 

 

Configure를 보면 잘 된것을 확인할 수 있습니다. AssetBundles 폴더 안에 무언가가 생겼습니다. 또한 StreamingAssets폴더도 생겼습니다.

DownloadFromServer.cs 파일을 하나 만듭니다.

아래와 같이 입력한다.

DownloadFromServer.cs

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
public class DownloadFromServer : MonoBehaviour
{
    private const string downloadURL = "https://downloadj.run.goorm.io";
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(DownloadAssets());
    }

    // Update is called once per frame
    void Update()
    {
    }

    IEnumerator DownloadAssets()
    {
        UnityWebRequest www = UnityWebRequest.Get(downloadURL);
        yield return www.SendWebRequest();

        if(www.isNetworkError || www.isHttpError)
        {
            Debug.Log(www.error);
        }
        else
        {
            File.WriteAllBytes(Path.Combine(Application.streamingAssetsPath, "myasset"), www.downloadHandler.data);
            Debug.Log("파일이 Assets/StreamingAssets에 저장되었습니다.");
        }

        /*
        WWW www = new WWW(downloadURL);

        yield return www;

        if (www.isDone)
        {
            Debug.Log(www.text);
            File.WriteAllBytes(Path.Combine(Application.streamingAssetsPath, "myasset"), www.bytes);
            Debug.Log("파일이 Assets/StreamingAssets에 저장되었습니다.");
        }
        */
    }
}

 

구름IDE에서 컨테이너를 생성한다. express로 설정한다음 실행하기 버튼 클릭. (추가 모듈/패키지는 설치할 필요 없다)

 

실행버튼. 클릭

download.js파일을 하나 만듭니다.

download.js

var fs= require('fs');	// 파일 시스템 모듈
var express = require('express');	// express 모듈
var app = express();	//express 객체 생성
var http = require('http');		// Http 웹 서버 모듈
var server = http.createServer(app); // 서버 객체 생성

app.set('port', 8080); 	// 서버 포트 설정

server.listen(app.get('port'), function() { // 서버 가동
	console.log('Download server listening on port ' + app.get('port'));
});

app.get('/', function(req, res) {
	var fileName = 'myasset';
	console.log(__dirname + '/public/' + fileName);
	fs.exists(__dirname + '/public/' + fileName, function(exists) {
		if(exists){
			fs.readFile(__dirname + '/public/' + fileName, function(err, data){
				var file = __dirname + '/public/' + fileName;
				res.download(file);
			});
		} else {
			res.end('파일이 존재하지 않습니다.');
		}
	});
});

 

구름ide 프로젝트 속서에 들어가서 URL을 하나 만들어줍니다. (808 포트로)

잘 내려받아지는지 테스트 해봅시다.

node download.js입력하여 서버를 실행합니다.

myasset 파일이 잘 다운로드 됩니다.

 

Unity로 돌아가서 LoadFromFileExample.cs 파일을 하나 만든다.

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class LoadFromFileExample : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(StartAssetBundle());
    }

    // Update is called once per frame
    void Update()
    {
    }

    IEnumerator StartAssetBundle()
    {
        var fileStream = new FileStream(Path.Combine(Application.streamingAssetsPath, "myasset"), FileMode.Open, FileAccess.Read);
        var bundleLoadRequest = AssetBundle.LoadFromStreamAsync(fileStream);
        yield return bundleLoadRequest;

        var myLoadedAssetBundle = bundleLoadRequest.assetBundle;
        if(myLoadedAssetBundle == null)
        {
            Debug.Log("Failed to load AssetBundle!");
            yield break;
        }

        var assetLoadRequest = myLoadedAssetBundle.LoadAssetAsync<GameObject>("Y");
        yield return assetLoadRequest;

        GameObject prefab = assetLoadRequest.asset as GameObject;
        Instantiate(prefab);

        myLoadedAssetBundle.Unload(false);
    }
}

빈게임 오브젝트를 하나 생성해서 이름을 바꾸고 만들었던 스크립트 파일들을 붙여준다.

실행해보니 잘 저장 된다.

LoadFromFileExample을 추가하여 이 파일만 켜놓게 하고 실행하면 서버에서 받은 Y(Clone)이 Load된다. 

 

'게임 개발 > 유니티' 카테고리의 다른 글

Unity EditorWindow  (0) 2019.11.14
재사용 가능한 Object Pool  (0) 2019.10.15
Unity LOD Group에 오브젝트들이 충돌(Collider)이 일어나는지 확인하는 실험  (0) 2019.08.22
FireBase  (0) 2019.08.20
Photon Server - Unity  (0) 2019.08.19

거리에 따라 도형이 바뀌는데 충돌도 적용이 되는지 안되는지 실험해본다.

 

LOD Group을 만든 다음 자식으로 Sphere, Capsule, Cylinder를 넣어놓고 

각각의 LOD(Level of Detail)에 도형을 넣어놨다.

충돌 시킬 물체에 Rigidbody 컴포넌트를 붙인다. 

 

실행시켜서 박스를 빈 곳으로 움직여보니  Sphere Collider에 충돌이 일어난다.

'게임 개발 > 유니티' 카테고리의 다른 글

재사용 가능한 Object Pool  (0) 2019.10.15
유니티 Asset Bundle 만들기.  (0) 2019.08.29
FireBase  (0) 2019.08.20
Photon Server - Unity  (0) 2019.08.19
unity와 nodejs-MongoDB를 이용한 데이터 통신 테스트  (0) 2019.08.14

프로젝트 하나 만듬

Sphere랑 Plane을 하나씩 생성

GameObject 생성

GameObject의 이름을 TimerManager로 바꿈

Add Component 에서 TimerManager.cs를 생성

더블 클릭하여 TimeManager 스크립트를 실행

하기전에 GameObject하나 더 생성

GameObject를 RespawnPosition으로 이름을 바꿈

 Plane 위쪽으로 Position 값을 준다. 

 

Sphere 오브젝트를 프리펩스로 만듬.

바닥으로 떨어트리기 위해 Rigidbody 컴포넌트를 달아주고 Drag 값을 0.5로 바꿈 (공기 저항 값을 줘 살살 내려오게)

코루틴도 멈추는지 테스트 하기 위해 UGUI Text 생성

 

TimeManager.cs의 스크립트를 집어넣음

TimeManager.cs의 코드

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

public class TimeManager : MonoBehaviour
{
    public GameObject respawnPosotion;
    public GameObject sphereObj;

    public float slowdownFactor = 0.05f;
    public float slowdownLength = 2f;

    public Text countText;

    public void DoSlowMotion()
    {
        Time.timeScale = slowdownFactor;
        Time.fixedDeltaTime = Time.timeScale * .02f;
    }

    // Use this for initialization
    void Start()
    {
        StartCoroutine(ITimer());
    }

    private void KeyController()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            DoSlowMotion();
        }
        if (Input.GetButtonDown("Fire2"))
        {
            Time.timeScale = 1f;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(sphereObj, respawnPosotion.transform.position, respawnPosotion.transform.rotation);
        }
    }

    // Update is called once per frame
    void Update()
    {

        KeyController();

        // 점점 빨라짐
        //Time.timeScale += (1f / slowdownLength) * Time.unscaledDeltaTime;
        //Time.timeScale = Mathf.Clamp(Time.timeScale, 0f, 1f);
    }

    IEnumerator ITimer()
    {
        int i = 0;
        while (true)
        {
            countText.text = i.ToString();
            yield return new WaitForSeconds(0.1f);
            i++;
        }
    }
}

 

드래그해서 넣어주고 Factor, Length 값을 설정함.

 

실행

 

스페이스바를 누르면 공 생성. 마우스 왼쪽 버튼을 눌러 슬로우모션으로 만듬. 마우스 오른쪽 버튼을 눌러 슬로우 모션을 품.

위의 주석을 해제하면 자연스럽게 슬로우 모션이 풀림.

 

사운드도 슬로우 되는지 Audio source를 넣어봐서 실험해봤는데 사운드는 슬로우가 안됨.

슬로우를 하려면 Pitch 값을 조절해주는 코드를 만들어서 사용해야 됨.

 

 

 

참고 동영상

https://www.youtube.com/watch?v=0VGosgaoTsw&t=604s

https://docs.unity3d.com/kr/2018.1/Manual/ScriptingRuntimeUpgrade.html

 

스크립팅 런타임 업그레이드 - Unity 매뉴얼

2017.1 버전의 경우, 프로젝트 옵션에 따라 .NET 4.6을 실험적으로 사용할 수 있습니다. 이 옵션은 Scripting Backend 또는 Api Compatibility Level 위 플레이어 설정에 GUI로 위치하고 있습니다.

docs.unity3d.com

 

Edit -> Project Settings -> Player

Configuration -> Scripting Runtime Version

+ Recent posts