यूनिटी के लिए टॉप-डाउन प्लेयर कंट्रोलर ट्यूटोरियल

बहुत से लोग एफपीएस (फर्स्ट-पर्सन शूटर) और आरटीएस (रियल-टाइम स्ट्रैटेजी) जैसी गेम शैलियों से परिचित हैं, लेकिन ऐसे कई गेम भी हैं जो सिर्फ एक विशिष्ट श्रेणी में नहीं आते हैं। ऐसा ही एक गेम है टॉप-डाउन शूटर।

टॉप-डाउन शूटर एक गेम है जहां खिलाड़ी को टॉप-व्यू परिप्रेक्ष्य से नियंत्रित किया जाता है।

टॉप-डाउन शूटरों के उदाहरण हॉटलाइन मियामी, हॉटलाइन मियामी 2, ओरिजिनल ग्रैंड थेफ्ट ऑटो आदि हैं।

वैम्पायर सर्वाइवर्स 2

Unity में टॉप-डाउन कैरेक्टर कंट्रोलर बनाने के लिए, नीचे दिए गए चरणों का पालन करें।

चरण 1: स्क्रिप्ट बनाएं

इस ट्यूटोरियल के लिए हमें केवल एक स्क्रिप्ट की आवश्यकता होगी।

  • एक नई स्क्रिप्ट बनाएं, इसे SC_TopDownController नाम दें, इसमें से सब कुछ हटा दें, और नीचे दिए गए कोड को इसके अंदर पेस्ट करें:

SC_TopDownController.cs

using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]

public class SC_TopDownController : MonoBehaviour
{
    //Player Camera variables
    public enum CameraDirection { x, z }
    public CameraDirection cameraDirection = CameraDirection.x;
    public float cameraHeight = 20f;
    public float cameraDistance = 7f;
    public Camera playerCamera;
    public GameObject targetIndicatorPrefab;
    //Player Controller variables
    public float speed = 5.0f;
    public float gravity = 14.0f;
    public float maxVelocityChange = 10.0f;
    public bool canJump = true;
    public float jumpHeight = 2.0f;
    //Private variables
    bool grounded = false;
    Rigidbody r;
    GameObject targetObject;
    //Mouse cursor Camera offset effect
    Vector2 playerPosOnScreen;
    Vector2 cursorPosition;
    Vector2 offsetVector;
    //Plane that represents imaginary floor that will be used to calculate Aim target position
    Plane surfacePlane = new Plane();

    void Awake()
    {
        r = GetComponent<Rigidbody>();
        r.freezeRotation = true;
        r.useGravity = false;

        //Instantiate aim target prefab
        if (targetIndicatorPrefab)
        {
            targetObject = Instantiate(targetIndicatorPrefab, Vector3.zero, Quaternion.identity) as GameObject;
        }

        //Hide the cursor
        Cursor.visible = false;
    }

    void FixedUpdate()
    {
        //Setup camera offset
        Vector3 cameraOffset = Vector3.zero;
        if (cameraDirection == CameraDirection.x)
        {
            cameraOffset = new Vector3(cameraDistance, cameraHeight, 0);
        }
        else if (cameraDirection == CameraDirection.z)
        {
            cameraOffset = new Vector3(0, cameraHeight, cameraDistance);
        }

        if (grounded)
        {
            Vector3 targetVelocity = Vector3.zero;
            // Calculate how fast we should be moving
            if (cameraDirection == CameraDirection.x)
            {
                targetVelocity = new Vector3(Input.GetAxis("Vertical") * (cameraDistance >= 0 ? -1 : 1), 0, Input.GetAxis("Horizontal") * (cameraDistance >= 0 ? 1 : -1));
            }
            else if (cameraDirection == CameraDirection.z)
            {
                targetVelocity = new Vector3(Input.GetAxis("Horizontal") * (cameraDistance >= 0 ? -1 : 1), 0, Input.GetAxis("Vertical") * (cameraDistance >= 0 ? -1 : 1));
            }
            targetVelocity *= speed;

            // Apply a force that attempts to reach our target velocity
            Vector3 velocity = r.velocity;
            Vector3 velocityChange = (targetVelocity - velocity);
            velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
            velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
            velocityChange.y = 0;
            r.AddForce(velocityChange, ForceMode.VelocityChange);

            // Jump
            if (canJump && Input.GetButton("Jump"))
            {
                r.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
            }
        }

        // We apply gravity manually for more tuning control
        r.AddForce(new Vector3(0, -gravity * r.mass, 0));

        grounded = false;

        //Mouse cursor offset effect
        playerPosOnScreen = playerCamera.WorldToViewportPoint(transform.position);
        cursorPosition = playerCamera.ScreenToViewportPoint(Input.mousePosition);
        offsetVector = cursorPosition - playerPosOnScreen;

        //Camera follow
        playerCamera.transform.position = Vector3.Lerp(playerCamera.transform.position, transform.position + cameraOffset, Time.deltaTime * 7.4f);
        playerCamera.transform.LookAt(transform.position + new Vector3(-offsetVector.y * 2, 0, offsetVector.x * 2));

        //Aim target position and rotation
        targetObject.transform.position = GetAimTargetPos();
        targetObject.transform.LookAt(new Vector3(transform.position.x, targetObject.transform.position.y, transform.position.z));

        //Player rotation
        transform.LookAt(new Vector3(targetObject.transform.position.x, transform.position.y, targetObject.transform.position.z));
    }

    Vector3 GetAimTargetPos()
    {
        //Update surface plane
        surfacePlane.SetNormalAndPosition(Vector3.up, transform.position);

        //Create a ray from the Mouse click position
        Ray ray = playerCamera.ScreenPointToRay(Input.mousePosition);

        //Initialise the enter variable
        float enter = 0.0f;

        if (surfacePlane.Raycast(ray, out enter))
        {
            //Get the point that is clicked
            Vector3 hitPoint = ray.GetPoint(enter);

            //Move your cube GameObject to the point where you clicked
            return hitPoint;
        }

        //No raycast hit, hide the aim target by moving it far away
        return new Vector3(-5000, -5000, -5000);
    }

    void OnCollisionStay()
    {
        grounded = true;
    }

    float CalculateJumpVerticalSpeed()
    {
        // From the jump height and gravity we deduce the upwards speed 
        // for the character to reach at the apex.
        return Mathf.Sqrt(2 * jumpHeight * gravity);
    }
}

चरण 2: शेडर बनाएं

इस ट्यूटोरियल में एक कस्टम शेडर की भी आवश्यकता होती है, जिसकी आवश्यकता लक्ष्य लक्ष्य को शेष ऑब्जेक्ट्स (हमेशा शीर्ष पर) को ओवरले करने के लिए होती है।

  • प्रोजेक्ट व्यू पर राइट-क्लिक करें -> क्रिएट -> शेडर -> स्टैंडआर्ट सरफेस शेडर
  • शेडर का नाम बताएं "Cursor"

  • शेडर खोलें, उसके अंदर की सभी चीज़ें हटा दें और फिर नीचे दिया गया कोड चिपकाएँ:

कर्सर.shader

Shader "Custom/FX/Cursor" {
	Properties {
		_MainTex ("Base", 2D) = "white" {}
	}
	
	CGINCLUDE

		#include "UnityCG.cginc"

		sampler2D _MainTex;
		
		half4 _MainTex_ST;
						
		struct v2f {
			half4 pos : SV_POSITION;
			half2 uv : TEXCOORD0;
		};

		v2f vert(appdata_full v) {
			v2f o;
			
			o.pos = UnityObjectToClipPos (v.vertex);	
			o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
					
			return o; 
		}
		
		fixed4 frag( v2f i ) : COLOR {	
			return tex2D (_MainTex, i.uv.xy);
		}
	
	ENDCG
	
	SubShader {
		Tags { "RenderType" = "Transparent" "Queue" = "Transparent+100"}
		Cull Off
		Lighting Off
		ZWrite Off
		ZTest Always
		Fog { Mode Off }
		Blend SrcAlpha OneMinusSrcAlpha
		
	Pass {
	
		CGPROGRAM
		
		#pragma vertex vert
		#pragma fragment frag
		#pragma fragmentoption ARB_precision_hint_fastest 
		
		ENDCG
		 
		}
				
	} 
	FallBack Off
}

चरण 3: टॉप-डाउन कैरेक्टर कंट्रोलर सेट करें

आइए एक टॉप-डाउन कैरेक्टर कंट्रोलर स्थापित करें:

  • एक नया गेमऑब्जेक्ट बनाएं और उसे कॉल करें "Player"
  • एक नया घन बनाएं और उसे स्केल करें (मेरे मामले में स्केल है (1, 2, 1))
  • दूसरा क्यूब बनाएं, इसे बहुत छोटा स्केल करें, और इसे ऊपरी क्षेत्र में ले जाएं (यह केवल यह जानने के लिए है कि खिलाड़ी किस दिशा में देख रहा है)
  • दोनों क्यूब्स को "Player" ऑब्जेक्ट के अंदर ले जाएं और उनके BoxCollider घटकों को हटा दें

अब, आगे बढ़ने से पहले, आइए लक्ष्य लक्ष्य प्रीफ़ैब बनाएं:

  • एक नया गेमऑब्जेक्ट बनाएं और उसे कॉल करें "AimTarget"
  • एक नया क्वाड (गेमऑब्जेक्ट -> 3डी ऑब्जेक्ट -> क्वाड) बनाएं और इसे "AimTarget" ऑब्जेक्ट के अंदर ले जाएं
  • नीचे दिए गए टेक्सचर को एक क्वाड में असाइन करें और मटेरियल शेडर को इसमें बदलें 'Custom/FX/Cursor'

लाल बिंदु क्रॉसहेयर

  • "AimTarget" को प्रीफ़ैब में सहेजें और इसे दृश्य से हटा दें

प्लेयर इंस्टेंस पर वापस जाएं:

  • "Player" ऑब्जेक्ट में SC_TopDownController स्क्रिप्ट संलग्न करें (आप देखेंगे कि इसमें कुछ अतिरिक्त घटक जैसे कि रिगिडबॉडी और कैप्सूलकोलाइडर जोड़े गए हैं)
  • कैप्सूलकोलाइडर को तब तक स्केल करें जब तक यह प्लेयर मॉडल से मेल न खा जाए (मेरे मामले में ऊंचाई 2 पर सेट है और केंद्र (0, 1, 0) पर सेट है)

  • और अंत में, SC_TopDownController में "Player Camera" और "Target Indicator Prefab" वेरिएबल असाइन करें

प्लेयर इंस्टेंस अब तैयार है, आइए इसका परीक्षण करें:

Sharp Coder वीडियो प्लेयर

सब कुछ उम्मीद के मुताबिक काम करता है।

स्रोत
📁TopDownCharacterController.unitypackage1.44 MB
सुझाए गए लेख
एकता में खिलाड़ी आंदोलन बनाना
एकता के लिए प्लेयर 3डी और 2डी वॉल जंप ट्यूटोरियल
यूनिटी के लिए RTS और MOBA प्लेयर कंट्रोलर
यूनिटी के लिए रिगिडबॉडी-आधारित प्लैनेटरी प्लेयर कंट्रोलर
यूनिटी में 2डी प्लेटफ़ॉर्मर कैरेक्टर कंट्रोलर में डबल जंप सपोर्ट जोड़ना
एकता के लिए 3डी वर्म नियंत्रक ट्यूटोरियल
एकता के लिए टॉर्च ट्यूटोरियल