using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class AnimateTiledTexture : MonoBehaviour
{
public int _columns = 2; // The number of columns of the texture
public int _rows = 2; // The number of rows of the texture
public Vector2 _scale = new Vector3(1f, 1f); // Scale the texture. This must be a non-zero number. negative scale flips the image
public Vector2 _offset = Vector2.zero; // You can use this if you do not want the texture centered. (These are very small numbers .001)
public Vector2 _buffer = Vector2.zero; // You can use this to buffer frames to hide unwanted grid lines or artifacts
public float _framesPerSecond = 10f; // Frames per second that you want to texture to play at
public bool _playOnce = false; // Enable this if you want the animation to only play one time
public bool _disableUponCompletion = false; // Enable this if you want the texture to disable the renderer when it is finished playing
public bool _enableEvents = false; // Enable this if you want to register an event that fires when the animation is finished playing
public bool _playOnEnable = true; // The animation will play when the object is enabled
public bool _newMaterialInstance = false; // Set this to true if you want to create a new material instance
private int _index = 0; // Keeps track of the current frame
private Vector2 _textureSize = Vector2.zero; // Keeps track of the texture scale
private Material _materialInstance = null; // Material instance of the material we create (if needed)
private bool _hasMaterialInstance = false; // A flag so we know if we have a material instance we need to clean up (better than a null check i think)
private bool _isPlaying = false; // A flag to determine if the animation is currently playing
public delegate void VoidEvent(); // The Event delegate
private List<VoidEvent> _voidEventCallbackList; // A list of functions we need to call if events are enabled
// Use this function to register your callback function with this script
public void RegisterCallback(VoidEvent cbFunction)
{
// If events are enabled, add the callback function to the event list
if (_enableEvents)
_voidEventCallbackList.Add(cbFunction);
else
Debug.LogWarning("AnimateTiledTexture: You are attempting to register a callback but the events of this object are not enabled!");
}
// Use this function to unregister a callback function with this script
public void UnRegisterCallback(VoidEvent cbFunction)
{
// If events are enabled, unregister the callback function from the event list
if (_enableEvents)
_voidEventCallbackList.Remove(cbFunction);
else
Debug.LogWarning("AnimateTiledTexture: You are attempting to un-register a callback but the events of this object are not enabled!");
}
public void Play()
{
// If the animation is playing, stop it
if (_isPlaying)
{
StopCoroutine("updateTiling");
_isPlaying = false;
}
// Make sure the renderer is enabled
GetComponent<Renderer>().enabled = true;
//Because of the way textures calculate the y value, we need to start at the max y value
_index = _columns;
// Start the update tiling coroutine
StartCoroutine(updateTiling());
}
public void ChangeMaterial(Material newMaterial, bool newInstance = false)
{
if (newInstance)
{
// First check our material instance, if we already have a material instance
// and we want to create a new one, we need to clean up the old one
if (_hasMaterialInstance)
Object.Destroy(GetComponent<Renderer>().sharedMaterial);
// create the new material
_materialInstance = new Material(newMaterial);
// Assign it to the renderer
GetComponent<Renderer>().sharedMaterial = _materialInstance;
// Set the flag
_hasMaterialInstance = true;
}
else // if we dont have create a new instance, just assign the texture
GetComponent<Renderer>().sharedMaterial = newMaterial;
// We need to recalc the texture size (since different material = possible different texture)
CalcTextureSize();
// Assign the new texture size
GetComponent<Renderer>().sharedMaterial.SetTextureScale("_MainTex", _textureSize);
}
private void Awake()
{
// Allocate memory for the events, if needed
if (_enableEvents)
_voidEventCallbackList = new List<VoidEvent>();
//Create the material instance, if needed. else, just use this function to recalc the texture size
ChangeMaterial(GetComponent<Renderer>().sharedMaterial, _newMaterialInstance);
}
private void OnDestroy()
{
// If we wanted new material instances, we need to destroy the material
if (_hasMaterialInstance)
{
Object.Destroy(GetComponent<Renderer>().sharedMaterial);
_hasMaterialInstance = false;
}
}
// Handles all event triggers to callback functions
private void HandleCallbacks(List<VoidEvent> cbList)
{
// For now simply loop through them all and call yet.
for (int i = 0; i < cbList.Count; ++i)
cbList[i]();
}
private void OnEnable()
{
CalcTextureSize();
if (_playOnEnable)
Play();
}
private void CalcTextureSize()
{
//set the tile size of the texture (in UV units), based on the rows and columns
_textureSize = new Vector2(1f / _columns, 1f / _rows);
// Add in the scale
_textureSize.x = _textureSize.x / _scale.x;
_textureSize.y = _textureSize.y / _scale.y;
// Buffer some of the image out (removes gridlines and stufF)
_textureSize -= _buffer;
}
// The main update function of this script
private IEnumerator updateTiling()
{
_isPlaying = true;
// This is the max number of frames
int checkAgainst = (_rows * _columns);
while (true)
{
// If we are at the last frame, we need to either loop or break out of the loop
if (_index >= checkAgainst)
{
_index = 0; // Reset the index
// If we only want to play the texture one time
if (_playOnce)
{
if (checkAgainst == _columns)
{
// We are done with the coroutine. Fire the event, if needed
if(_enableEvents)
HandleCallbacks(_voidEventCallbackList);
if (_disableUponCompletion)
gameObject.GetComponent<Renderer>().enabled = false;
// turn off the isplaying flag
_isPlaying = false;
// Break out of the loop, we are finished
yield break;
}
else
checkAgainst = _columns; // We need to loop through one more row
}
}
// Apply the offset in order to move to the next frame
ApplyOffset();
//Increment the index
_index++;
// Wait a time before we move to the next frame. Note, this gives unexpected results on mobile devices
yield return new WaitForSeconds(1f / _framesPerSecond);
}
}
private void ApplyOffset()
{
//split into x and y indexes. calculate the new offsets
Vector2 offset = new Vector2((float)_index / _columns - (_index / _columns), //x index
1 - ((_index / _columns) / (float)_rows)); //y index
// Reset the y offset, if needed
if (offset.y == 1)
offset.y = 0.0f;
// If we have scaled the texture, we need to reposition the texture to the center of the object
offset.x += ((1f / _columns) - _textureSize.x) / 2.0f;
offset.y += ((1f / _rows) - _textureSize.y) / 2.0f;
// Add an additional offset if the user does not want the texture centered
offset.x += _offset.x;
offset.y += _offset.y;
// Update the material
GetComponent<Renderer>().sharedMaterial.SetTextureOffset("_MainTex", offset);
}
}
Shader "Unlit/SimpleUnlitTexturedShader"
{
Properties
{
// we have removed support for texture tiling/offset,
// so make them not be displayed in material inspector
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
// use "vert" function as the vertex shader(정점쉐이더)
#pragma vertex vert
// use "frag" function as the pixel (fragment) shader(픽셀/프레그먼트 쉐이더)
#pragma fragment frag
#include "UnityCG.cginc" // 셰이더 컴파일을 하는데 포함시키고자하는 라이브러리에 지정
//버텍스 쉐이더를 넣는곳- 정점 데이터를 appdata 구조를 통해 수집하고 이는 정점 함수로 전달한다.
struct appdata
{
float4 vertex : POSITION; // 버텍스 위치
float2 uv : TEXCOORD0; // 텍스쳐 좌표
};
// 버텍스 쉐이더를 내보내는곳.- 정점함수는 v2f(vertex to fragment) 데이터 구조 멤버들의 내용을 채우고 이를 프래그먼트 함수의 인자로 전달한다.
struct v2f
{
float2 uv : TEXCOORD0; // 텍스쳐 좌표
float4 vertex : SV_POSITION; // 클립공간위치
};
// 샘플링 할 텍스처- 변수선언
sampler2D _MainTex;
// vertex shader
v2f vert (appdata v)
{
v2f o;
// 위치를 클립 공간으로 변환
// (모델 * 뷰 * 투영 행렬로 곱하기)
o.vertex = UnityObjectToClipPos(v.vertex);// UnityObjectToClipPos-정점 좌표 공간에서 레스터라이저가 사용하는 좌표 공간으로 변환
// 텍스처 좌표를 전달하기
o.uv = v.uv;
return o;
}
// 픽셀 쉐이더-낮은 정밀도를 반환합니다 ( "fixed4"타입)
// color ("SV_Target" semantic) 하나의 프레그먼트 색상 출력을 의미함.
fixed4 frag (v2f i) : SV_Target
{
// 샘플 텍스처,반환
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
버텍스 셰이더(Vertex Shader)는 3D 모델의 각 버텍스에서 실행되는 프로그램입니다. 많은 경우 버텍스 셰이더는 특별히 흥미로운 동작을 하지는 않습니다. 여기서는 버텍스 위치를 오브젝트 공간에서 이른바 “클립 공간”으로 변환하기만 합니다. GPU가 오브젝트를 화면에 래스터화하기 위해 클립 공간을 사용합니다. 프래그먼트 셰이더에서 텍스처를 샘플링하기 위해 필요로 합니다.
프래그먼트 셰이더(Fragment Shader)는 오브젝트가 화면에서 차지하고 있는 모든 픽셀마다 실행되는 프로그램이며 보통 각 픽셀의 컬러를 계산하고 출력하기 위해 사용됩니다. 화면에는 보통 수백만 개의 픽셀이 있으며 프래그먼트 셰이더는 이 모든 픽셀에 대해 실행됩니다! 프래그먼트 셰이더를 최적화하는 것은 전반적인 게임 성능에 있어 매우 중요한 부분입니다.
List = 정수형, 문자형등 형식을 정해서 넣어서 사용하므로 ArrayList보다 성능이 더 좋다고 할수 있다.
HashTable = 특정키값을 정해서 리스트를 만드는 기능이다. [만수(특정값 , 10000)]
Dictionary = HashTable과 유사하고 List처럼 정해진 형식을 사용한다.
Queue = 순서대로 값을 넣고 순서대로 값을 빼내서 없앨때 사용된다.
Queue<int> qqu = new Queue<int>();
void Start()
{
qqu.Enqueue(1);
qqu.Enqueue(3);
qqu.Enqueue(5);
if (qqu.Count != 0)// 아무것도 없을때 에러가 나지 않게 if를 넣어준다.
print(qqu.Dequeue());
if (qqu.Count != 0)
print(qqu.Dequeue());
if (qqu.Count != 0)
print(qqu.Dequeue());
}
Stack= 순서대로 값을 넣고 반대순서대로 값을 없앨때 사용된다.(젠가는 위로 쌓아서 위에서 부터 제거한다.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class restart : MonoBehaviour
{
void Update()
{
if (Input.GetKey(KeyCode.Space))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}