Witam. Dostałem w swoje ręce 2 skrypty, każdy inaczej zbudowany, ale mający na celu sterować postacią. Ten który mnie bardziej interesuje jest niestety zrobiony wyłącznie pod klawiaturę, natomiast drugi pod między innymi touch screen. Zajmuję się grafiką 3D i z programowania umiem tyle co udało mi się liznąć kiedyś w technikum, no i potrafię zrozumieć kod, przynajmniej jego niektóre elementy. Oba skrypty zostały napisane pod Unity, ale to chyba bez większego znaczenia, a i można wynieść taką informację z samych skryptów. Poniżej przedstawiam kolejno wersję pod klawiaturę oraz touch screen.

PlayerController

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(PlayerPhysics))]
public class PlayerController : Entity {

// Player Handling
public float gravity = 20;
public float walkSpeed = 8;
public float runSpeed = 12;
public float acceleration = 30;
public float jumpHeight = 12;
public float slideDeceleration = 10;

private float initiateSlideThreshold = 9;

// System
private float animationSpeed;
private float currentSpeed;
private float targetSpeed;
private Vector2 amountToMove;
private float moveDirX;

// States
private bool jumping;
private bool sliding;
private bool wallHolding;
private bool stopSliding;

// Components
private PlayerPhysics playerPhysics;
private Animator animator;
private GameManager manager;

void Start () {
playerPhysics = GetComponent<PlayerPhysics>();
animator = GetComponent<Animator>();
manager = Camera.main.GetComponent<GameManager>();
animator.SetLayerWeight(1,1);
}

void Update () {
// Reset acceleration upon collision
if (playerPhysics.movementStopped) {
targetSpeed = 0;
currentSpeed = 0;
}

// If player is touching the ground
if (playerPhysics.grounded) {
amountToMove.y = 0;

if (wallHolding) {
wallHolding = false;
animator.SetBool("Wall Hold", false);
}

// Jump logic
if (jumping) {
jumping = false;
animator.SetBool("Jumping",false);
}

// Slide logic
if (sliding) {
if (Mathf.Abs(currentSpeed) < .25f || stopSliding) {
stopSliding = false;
sliding = false;
animator.SetBool("Sliding",false);
playerPhysics.ResetCollider();
}
}

// Slide Input
if (Input.GetButtonDown("Slide")) {
if (Mathf.Abs(currentSpeed) > initiateSlideThreshold) {
sliding = true;
animator.SetBool("Sliding",true);
targetSpeed = 0;

playerPhysics.SetCollider(new Vector3(10.3f,1.5f,3), new Vector3(.35f,.75f,0));
}
}
}
else {
if (!wallHolding) {
if (playerPhysics.canWallHold) {
wallHolding = true;
animator.SetBool("Wall Hold", true);
}
}
}

// Jump Input
if (Input.GetButtonDown("Jump")) {
if (sliding) {
stopSliding = true;
}
else if (playerPhysics.grounded || wallHolding) {
amountToMove.y = jumpHeight;
jumping = true;
animator.SetBool("Jumping",true);

if (wallHolding) {
wallHolding = false;
animator.SetBool("Wall Hold", false);
}
}
}

// Set animator parameters
animationSpeed = IncrementTowards(animationSpeed,Mathf.Abs(targetSpeed),acceleration);
animator.SetFloat("Speed",animationSpeed);

// Input
moveDirX = Input.GetAxisRaw("Horizontal");
if (!sliding) {
float speed = (Input.GetButton("Run"))?runSpeed:walkSpeed;
targetSpeed = moveDirX * speed;
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,acceleration);

// Face Direction
if (moveDirX !=0 && !wallHolding) {
transform.eulerAngles = (moveDirX>0)?Vector3.up * 180:Vector3.zero;
}
}
else {
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,slideDeceleration);
}

// Set amount to move
amountToMove.x = currentSpeed;

if (wallHolding) {
amountToMove.x = 0;
if (Input.GetAxisRaw("Vertical") != -1) {
amountToMove.y = 0;
}
}

amountToMove.y -= gravity * Time.deltaTime;
playerPhysics.Move(amountToMove * Time.deltaTime, moveDirX);

}

void OnTriggerEnter(Collider c) {
if (c.tag == "Checkpoint") {
manager.SetCheckpoint(c.transform.position);
}
if (c.tag == "Finish") {
manager.EndLevel();
}
}

// Increase n towards target by speed
private float IncrementTowards(float n, float target, float a) {
if (n == target) {
return n;
}
else {
float dir = Mathf.Sign(target - n); // must n be increased or decreased to get closer to target
n += a * Time.deltaTime * dir;
return (dir == Mathf.Sign(target-n))? n: target; // if n has now passed target then return target, otherwise return n
}
}
}

On zawiera głównie sterowanie + skrypty pisane już osobno, ale ich już raczej nie muszę tutaj wstawiać. Skrypt pod touch jest podzielony na 4 części co dodatkowo mnie dezorientuje w temacie.

PlayerMovement

using UnityEngine;
using System.Collections;

public class PlayerMovement : MonoBehaviour
{
public float speed = 500f, jumpHeight = 500f;
Transform myTrans;
Rigidbody2D myBody;
Vector2 movement;//used as temp holder variable before applying to velocity
bool isGrounded = true;

void Start ()
{
myTrans = this.transform;
myBody = this.rigidbody2D;
}

void Update ()
{
//Check if the player is grounded or not
isGrounded = Physics2D.Linecast(myTrans.position,
GameObject.Find(this.name+"/tag_ground").transform.position,
LayerMask.NameToLayer("Player"));

//Just for visualization, not needed for gameplay
Debug.DrawLine (myTrans.position,
GameObject.Find(this.name+"/tag_ground").transform.position,
Color.red);

//Works for keyboards and joysticks
#if !UNITY_ANDROID && !UNITY_IPHONE && !UNITY_BLACKBERRY && !UNITY_WINRT
Move (Input.GetAxisRaw("Horizontal"));
if (Input.GetButtonDown ("Jump"))
Jump ();
#endif
}
//
//Separate Move and Jump so they can be called externally by TouchButtons
//
public void Move(float horizontal_input)
{
movement = myBody.velocity;

if(isGrounded)//we can only move left and right if on the ground
movement.x = horizontal_input * speed * Time.deltaTime;

//Apply the movement to the player
myBody.velocity = movement;
}
public void Jump()//we can only jump if on the ground
{
if(isGrounded)
myBody.velocity += jumpHeight * Vector2.up * Time.deltaTime;
}
}  

MoveButton

using UnityEngine;
using System.Collections;

public class MoveButton : TouchLogicV2
{
[Range(-1,1)]
public int moveDir = 1;//1=right;-1=left
PlayerMovement player;

void Start()
{
player = FindObjectOfType<PlayerMovement>();//This will find our player script, as long as there is only 1 GameObject with "PlayerMovement" on it
}

public override void OnTouchBegan()
{
//watch this touch for when it ends anywhere so we can slow down the player
touch2Watch = currTouch;
}

public override void OnTouchMoved()
{
player.Move (moveDir);
}
public override void OnTouchStayed()
{
player.Move (moveDir);
}
public override void OnTouchEndedAnywhere()
{
//run this check so other touches ending don't cause player to slow down
if(currTouch == touch2Watch)
player.Move(0);//do avoid annoying drift after letting go of button
}
}  

JumpButton

using UnityEngine;
using System.Collections;

public class JumpButton : TouchLogicV2
{
PlayerMovement player;
void Start()
{
player = FindObjectOfType<PlayerMovement>();
}

public override void OnTouchBegan()
{
player.Jump ();
}
}  

TouchLogicV2

using UnityEngine;
using System.Collections;

public class TouchLogicV2 : MonoBehaviour
{
public static int currTouch = 0;//so other scripts can know what touch is currently on screen
[HideInInspector]
public int touch2Watch = 64;
public virtual void Update()//If your child class uses Update, you must call base.Update(); to get this functionality
{
//is there a touch on screen?
if(Input.touches.Length <= 0)
{
OnNoTouches();
}
else //if there is a touch
{
//loop through all the the touches on screen
for(int i = 0; i < Input.touchCount; i++)
{
currTouch = i;
//executes this code for current touch (i) on screen
if(this.guiTexture != null && (this.guiTexture.HitTest(Input.GetTouch(i).position)))
{
//if current touch hits our guitexture, run this code
if(Input.GetTouch(i).phase == TouchPhase.Began)
{
OnTouchBegan();
touch2Watch = currTouch;
}
if(Input.GetTouch(i).phase == TouchPhase.Ended)
{
OnTouchEnded();
}
if(Input.GetTouch(i).phase == TouchPhase.Moved)
{
OnTouchMoved();
}
if(Input.GetTouch(i).phase == TouchPhase.Stationary)
{
OnTouchStayed();
}
}
//outside so it doesn't require the touch to be over the guitexture
switch(Input.GetTouch(i).phase)
{
case TouchPhase.Began:
OnTouchBeganAnywhere();
break;
case TouchPhase.Ended:
OnTouchEndedAnywhere();
break;
case TouchPhase.Moved:
OnTouchMovedAnywhere();
break;
case TouchPhase.Stationary:
OnTouchStayedAnywhere();
break;
}
}
}
}
//the default functions, define what will happen if the child doesn't override these functions
public virtual void OnNoTouches(){}
public virtual void OnTouchBegan(){print (name + " is not using OnTouchBegan");}
public virtual void OnTouchEnded(){}
public virtual void OnTouchMoved(){}
public virtual void OnTouchStayed(){}
public virtual void OnTouchBeganAnywhere(){}
public virtual void OnTouchEndedAnywhere(){}
public virtual void OnTouchMovedAnywhere(){}
public virtual void OnTouchStayedAnywhere(){}
}  

Przepraszam za długi post, ale naprawdę nie wiem gdzie mógłbym szukać pomocy dotyczącej tego typu tematu, więc mam nadzieję, że znajdę ją tutaj. To co mnie najbardziej interesuje to przerobienie pierwszego skryptu pod touch, wzorując się na pozostałych (lub nie, ale wygodniej będzie mi się dopasować do tutoriali).

Pozdrawiam,
DrComet