반응형

 

Rendertexture 기능을 이용해 UI에 캐릭터 모델을 나타 내는걸 진행해보았습니다.

 

 

기존에는 canvas 에서 해당 UI씬 마다 필요 캐릭터모델을 로드하고 위치하게 했엇는데,

Rendertexture 를 사용하면 한 캐릭터모델만 로드하여 사용할수 잇어 클라이언트 측면에서 이점이 있는걸로 생각이 됩니다.

 

 

 

-사용방법

 

1. 프로젝트에 Create / Rendertexure 로 렌더텍스쳐 파일을 생성합니다.

 

 

 

 

 

 

 

 

2. Size를 설정합니다. 사이즈가 크면 클수록 화질이 선명하게 나옵니다.

 Render 될 오브젝트(캐릭터)가 크게 비추게 원하시면 1024/1024 정도 사이즈로 설정해두면 좋습니다.

사이즈 값은 2제곱수로 해야합니다 (ex. 256/256 , 512/512  , ...)

 

 

 

 

3. 씬내에 카메라를 생성합니다

 - 카메라 TargetTexture에 생성한 RenderTexture를 할당합니다.

 - 카메라에 CullingMask는 선택 유무 입니다. 캐릭터만 보이고 싶다하면 캐릭터에 설정한 layer를 선택하게 되면

   Render 될때에 캐릭터만 보이게 될것입니다.

 - 카메라 Projection 은 Orthographic으로 합니다. UI 에 캐릭터를 나타낼것이므로 원근감이 필요없어서 그렇습니다. 

   만약 Render 타입이 3D 형태 라면 원근감이 느껴지는 Perspective를 사용하세요

 

 

 

 

 

 

 

4. 해당 UI에 RawImage를 만듭니다. ( 씬내 우클릭 -> UI -> RawImage )

 - 생성된 RawImage 에 생성한 RenderTexure를 할당합니다.

 - RawImage 사이즈 (width,height)로 렌더될 사이즈를 결정해줍니다. 

   (RawImage 사이즈 가 작게 표시할경우 위 2번에 Rendertexture의 size 를 256/256 정도로 해줘도 좋습니다,

    하지만 RawImage 사이즈가 UI 전역에해당하는 크기이다 하면 size는 1024/1024 이상으로 잡아 줘야, Render 시

    캐릭터가 꺠지지 않게 보입니다)

 - RawImage 사이즈 설정하게 되면 그림의 초록 부분에 오브젝트(캐릭터)가 보이게 될것입니다.

 

 

 

 

 

5. 씬에 생성한 카메라 바라보는 방향에 캐릭터를 생성합니다.

 - play 를 하면 UI에 RawImage 부분에 캐릭터가 보이는것을 확인할수 있습니다.

반응형
반응형

 

 

3D 구체(공을) 벽이나 바닥에 닿을시 계속 튕기게 (바운딩) 되게 해 보았습니다.

 

- 공에적용한 컴포넌트 

 1. Rigidbody 컴포넌트

 2. Sphere Collider 컴포넌트

 

 

 

- 설명

 

일반적으로 물리가 적용되어 공이 바운딩을 하긴 하나 여러차례 지날수록 바운딩 되지 않고 제자리에 잇거나 굴러 가기만 하죠. 

 

이번에는 공을 계속 튕기도록 해보았습니다. 

 

 

우선 아래 예시 움짤입니다

 

 

 

 

 

 

원리는 아래 그림처럼 공이 벽이나 바닥을 충돌했을때 충돌 접점을 알아낸후 
공과 충돌체의 역방향으로 Rigidbody.Addforce 하는겁니다

 

 

이제 공이 충돌되었을떄 처리 되는 코드 입니다.

void OnCollisionEnter(Collision collision)
    {
        
        
        
        ExcecuteReBounding();
    }
    
    
     void ExcecuteReBounding(Collision collision)
    {
      

        ContactPoint cp = collision.GetContact(0);
        Vector3 dir = Tr.position - cp.point; // 접촉지점에서부터 탄위치 의 방향
        rigidbody.AddForce((dir).normalized * 300f);
    }

 

Collision.GetContact 함수는 충돌시 충돌되는 접점의 정보를 반환해주는 함수 입니다.
반환되는 타입은 ContactPoint 이며  ContactPoint의 멤버변수인 Vector3 point 가

접촉된 지점을 의미합니다.

 

공의위치 - 접촉지점 = 밀어낼 방향 이 되므로 이방향으로 Addforce를 가해주면 공이 계속 튕기는 느낌을 줄수 있습니다.

 

 

이상 공 계속 튕기기 였습니다.

 

반응형
반응형

3D 유도탄만들기.

 

벡터 내적외적 이용해서 할려고 하는데 적용하기에는 시간이 걸려서 

이번 포스트에는 타겟 방향벡터 가지고 유도탄 만들기를 하겠습니다.

 

추후에 이 포스트에 벡터 내적외적 이용해서 구현한 방법도 추가해서 올릴게요~

 

 

 

우선 구현 움짤입니다

 

6개 로켓이 한방향으로 나가는 유도탄(유도체는 앞쪽에 회색기둥)

 

 

 

 

 

 

구현 코드내용입니다

private float dis;
private float speed;
private float waitTime;
public Transform TargetTr;


void Start()
{
   dis = Vector3.Distance(Tr.position, TargetTr.position);
   
   //포탄생성후 초반에 포탄이 벌어지듯이 연출하기위해
   //포탄의 회전을 캐릭터위치에서 포탄의 위치의 방향으로 놓습니다
   transform.rotation = Quaternion.LookRotation(transform.position - 캐릭터의위치);

}


void Update()
{
	DiffusionMissile_Move_Operation();
}

void DiffusionMissile_Move_Operation()
    {
        if (TargetTr == null) return;

        
        waitTime += Time.deltaTime;
        //1.5초 동안 천천히 forward 방향으로 전진합니다
        if (waitTime < 1.5f)
        {
            speed = Time.deltaTime;
            transform.Translate(Tr.forward * speed, Space.World);
        }
        else
        {
        // 1.5초 이후 타겟방향으로 lerp위치이동 합니다

            speed += Time.deltaTime;
            float t = speed / dis;

            Tr.position = Vector3.LerpUnclamped(Tr.position, TargetTr.position,  t   );

        }


		// 매프레임마다 타겟방향으로 포탄이 방향을바꿉니다
        //타겟위치 - 포탄위치 = 포탄이 타겟한테서의 방향
        Vector3 directionVec = TargetTr.position - Tr.position;
        Quaternion qua = Quaternion.LookRotation(directionVec);
        Tr.rotation = Quaternion.Slerp(Tr.rotation, qua, Time.deltaTime * 2f);
        


    }

 

포탄생성시 위치값은 랜덤으로 해줬습니다.

이후에 transform.rotation = Quaternion.LookRotation(transform.position - 캐릭터의위치); 에서

각 포탄의 방향을 공작날개같이 펼치듯이 하기 위해 방향을 변경합니다.

 

경과시간 1.5초 전 까지는 공작날개같이 펼쳐 놓도록한 포탄의 방향에서 forward 방향으로 전진 시켜줍니다.

 

경과시간 1.5이후에는 타겟으로 위치이동을합니다.

 

매프레임마다 포탄의 방향은 타겟방향으로 향하게 Slerp 처리 해줍니다.

 

위 유도탄 만들기 코드 중 DiffusionMissile_Move_Operation함수 만 보시면 될거같네요 

 

이상 유도탄 만들기 였습니다.

반응형
반응형

충돌범위 안에 있는 모든 충돌체를 가져와 참조 하고 싶다, 충돌범위안 모든 콜리더가 잇는 오브젝트를 알고 싶다

 

그러면 Physics.OverlapXXX 함수들을 사용하면 되는데요 .

Overlap함수 종류로는, OverlapBox , OverlapSphere , OverlapCapsule 가 있습니다.

 

이중에서 OverlapCapsule 함수 사용법을 알아보겟습니다 .

 

OverlapCapsule 함수 정의를 찾아보면 아래 와같습니다 

 

 

 

----------------------------------------------------------------------------------------------------------------------------------

public static Collider [] OverlapCapsule ( Vector3 point0 , Vector3 point1 , float radius , int layerMask = AllLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);

 

매개 변수

point0 start캡슐 의 구의 중심 .
point1 end캡슐 의 구의 중심 .
radius 캡슐의 반경입니다.
layerMask 레이어 마스크 캡슐을 전송할 때 선택적 colliders을 무시하는데 사용된다.
queryTriggerInteraction 이 쿼리가 트리거에 도달해야하는지 여부를 지정합니다.

----------------------------------------------------------------------------------------------------------------------------------

 

OverlapCapsule 함수에 들어가는 매개변수중에서 point0, point1 두 인자가 어떻게 값을 넣어야하는지 궁금햇습니다.

구글링해도 딱히 사용법도 안올라와서 제가 해봣습니다.

 

start캡슐 의 구의 중심 ? end캡슐 의 구의 중심? 무슨 말인가 했엇죠 

 

end캡슐 의 구의 중심 / start캡슐 의 구의 중심 . 아래 사진과같은 의미입니다.

 

사진에 명칭을 달리햇지만 (Pos1, Pos2)

 

결론적의미는 캡슐의 맨위쪽 위치와  맨아래쪽 위치를 말하는겁니다.

 

 

아래는 OverlapCapsule 함수 사용법 예시 입니다.

  void Update()
    {
    
    	//반경
	float radius = 5f;
        
        //캡슐의 맨아래 위치
        Vector3 pos1 = new Vector3(Tr.position.x, Tr.position.y-ConstHeight, Tr.position.z);
        //캡슐의 맨위 위치
        Vector3 pos2 = new Vector3(Tr.position.x, Tr.position.y + ConstHeight, Tr.position.z);

        Collider[] colls = Physics.OverlapCapsule(pos2, pos1, radius);

        for (int i = 0; i < colls.Length; i++)
        {

            _player = colls[i].GetComponent<Player_Script>();

            if(_player != null)
            {
               //...
            }
        }


        
    }

 

ConstHeight  변수는 임의지정한 높이 값입니다. 정해준 값에 따라 캡슐의 높이가 설정됩니다.

 

 

 

 

 

* 추가적으로 OverlapCapsuleNonAlloc 함수 사용법도 위와 동일합니다 .

OverlapCapsuleNonAlloc는 할당한 충돌체들을 반환하지않고 충돌한 갯수를 반환합니다. 그러므로 OverlapCapsule 사용할때보다 메모리 누적이 덜되기 때문에 게임부하에 덜주게 됩니다. 반대로 OverlapCapsule는 반환되는 충돌체들을이메모리할당하기 때문에 메모리 누적이 발생합니다.

 

 

 

이상  Physics.OverlapCapsule 함수 사용법 이었습니다.

반응형
반응형

Rigidbody 컴포넌트 사용시 해당 오브젝트에게 중력을 부여할수 있습니다.

 

그 중력 값은 Edit > Project setting > physics 가면 중력값 변경할수 있습니다.

 

혹은 스크립트 상에서  Physics.gravity = new Vector3(0,-10f,0); 와 같이 코드입력하여 제어 할수 있습니다.

 

 

위와같이 중력값을 변경하게 되면 Rigidbody 컴포넌트를 가진 오브젝트들이 영향을 받습니다.

 

오브젝트 개별적으로 중력값 다르게 하려면 어떻게 해야할까요 

 

 

오브젝트 개별적으로 중력값 다르게 하는 방법입니다 .

 

1. 해당 오브젝트에 Constant Force 컴포넌트를 추가 하고 Force 벡터 값에 원하는 중력값을 넣습니다.

 

 

 

 

2. 스크립트상에서 FixedUpdate () 함수문 안에 Rigidbody.Addforce 활용하는것입니다.

 

 float forceGravity = 50f;
    private void FixedUpdate()
    {
        rigidbody.AddForce(Vector3.down * forceGravity);
    }

 

 

위 두방법으로 하게되면 Physics.gravity 값을 받고 추가적으로 1번, 2번 방법의 값을 받아 

더 중력값을 받거나 덜 중력값을 받게 하여 오브젝트 개별적으로 중력값 줄수 있게 됩니다.

 

 

사용 예시)

 

- 특정 캐릭터는 점프후 낙하속도를 빠르게 하고싶다.

  (위 2번 방법으로는  y방향 값을 높여 주면됩니다)

 

 

이상, 오브젝트 개별적으로 중력값 다르게 하는 방법이었습니다.

반응형
반응형

Quaternion.Lerp 이나 Quaternion.Slerp 사용시 
회전이 목표 회전까지 스무스하게 일어나는데요 ,

회전이 다 끝났는지 체킹하는 법입니다 .

 

아래 예시입니다.

 

void Chk_rotate()
{
	//1번째 방법 자신과 target의 eulerAngles의 인자값(y)으로 확인하기 (y축회전 기준일때)
	float diff = player.transform.rotation.eulerAngles.y - targetRotation.eulerAngles.y; 
	float dergee = 1; 
	if (Mathf.Abs (diff) <= dergee) 
	{ 
   	 Debug.Log("ready");
   	 }
    
    
    
    //2번쨰방법 자신과 target의 Quaternion.angle로 두사이각으로 확인하기
     float angle = Quaternion.Angle(player.transform.rotation, 
     TargetTransform.rotation);
     
     if(angle <= 0)
      debug.Log("target 회전 완료");
    
    
 }
반응형
반응형

 

한 애니메이션에 에니메이션 이벤트를 두웠는데

 

하나의 AudioSource 로 이벤트 발생시 사운드가 발생됩니다.  에니메이션 길이는 0.1초 이며 사운드 길이는 3초 입니다. 

 

0.1초마다 애니메이션이 재생되면서 사운드가 재생이되면 

 

3초 에 30개 사운드가 발생됩니다 .

 

재생되엇던 하나의 사운드가 끝나기도 전에 계속 같은 사운드가 재생됩니다. 

 

100개 정도 사운드가 재생이되더니 유니티가 멈췃습니다. 

 

유니티 과부하인거같아요 ....

 

 

그래서 같은 사운드로 재생 갯수를 제한두어겟다는 생각을 햇습니다 .

(재생갯수 30개 정도 두니 멈춤현상없어졋습니다)

 

 

아래 예제 소스입니다.

 private Dictionary<AudioClip, List<float>> soundOneShot = new Dictionary<AudioClip, List<float>>();
 private int MaxDuplicateOneShotAudioClips = 30; // oneshot이 최대 겹처서 재생될수 잇는 수


void PlayOneShotSound(AudioSource source, AudioClip clip, float volumeScale)
    {

        //해당 클립당 재생되고 잇는 사운드 수를 계산하기위해 아래와같이 처리한다
        // 재생수가 max 만큼이면 재생안한다
        if(!soundOneShot.ContainsKey(clip))
        {
            soundOneShot[clip] = new List<float>() { volumeScale };
        }
        else
        {
            int count = soundOneShot[clip].Count;
            //한클립당 현재 재생수가 30개 넘으면 리턴한다
            if (count == MaxDuplicateOneShotAudioClips) return;
            soundOneShot[clip].Add(volumeScale);
        }
        int count1 = soundOneShot[clip].Count;
        Debug.Log(clip.name + " 재생갯수 : " + count1);
      

        source.PlayOneShot(clip, volumeScale);
        StartCoroutine(RemoveVolumeFromClip(clip, volumeScale));
     
    }

    private  IEnumerator RemoveVolumeFromClip(AudioClip clip, float volume)
    {
        // 재생 시간동안기다리고 그후에 저장된 값을 지운다
        yield return new WaitForSeconds(clip.length);

        List<float> volumes;
        if (soundOneShot.TryGetValue(clip, out volumes))
        {
            volumes.Remove(volume);
        }
    }

 

 

반응형
반응형
public class particleMove : MonoBehaviour {
	ParticleSystem ps;
	ParticleSystem.Particle[] m_Particles;
	public Transform target;
	public float speed = 5f;
	private int numParticlesAlive;
    private float step = 0;


    void Start () {
		ps = GetComponent<ParticleSystem>();
		if (!GetComponent<Transform>()){
			GetComponent<Transform>();
		}
	}



    public void InitAttractorMove( Transform _target)
    {
        target = _target;

        step = 0;

        distance = 0;
    }
    
    
    
    
	void Update () 
    {
        if(m_Particles == null)
		    m_Particles = new ParticleSystem.Particle[ps.main.maxParticles];

		numParticlesAlive = ps.GetParticles(m_Particles);
	    step = speed * Time.deltaTime;
		for (int i = 0; i < numParticlesAlive; i++)
        {
			m_Particles[i].position = Vector3.MoveTowards(m_Particles[i].position, target.position, step);

                  
		}

     
        ps.SetParticles(m_Particles, numParticlesAlive);

        
	}
}

 

반응형

+ Recent posts