- Home /
How to do a multiplayer split-screen game on one computer?
Hey guys, so what I did was take four duplicated characters with four cameras attached to all of them, and I modified the normalized view port rect so that in the game it appears split-screen. The problem is, when I control the characters in the game with one keyboard it controls all of them, and when I plug in more keyboards they all still control everybody. So my question is, how can isolate one keyboard per a player?
Answer by BigBlob · Apr 07, 2012 at 08:32 PM
Well I think that to have multiple keyboards maybe require scripting, since it is related to multiple devices. Maybe there is a configuration in the Input.I found and answer that relates to yours - scripts have to include "`GetAxis`" when yore about to state Input.
Felipe
Answer by HolyCrapf · Apr 08, 2012 at 06:11 PM
Okay, so how would that look in a script. I myself am not familiarized at all with scripting, so I am not sure where to put that in the script. The script is the one used in the AngryBots demo for the character titled PlayerMoveController.js. Here is the script though:
pragma strict
// Objects to drag in public var motor : MovementMotor; public var character : Transform; public var cursorPrefab : GameObject; public var joystickPrefab : GameObject;
// Settings public var cameraSmoothing : float = 0.01; public var cameraPreview : float = 2.0f;
// Cursor settings public var cursorPlaneHeight : float = 0; public var cursorFacingCamera : float = 0; public var cursorSmallerWithDistance : float = 0; public var cursorSmallerWhenClose : float = 1;
// Private memeber data private var mainCamera : Camera;
private var cursorObject : Transform; private var joystickLeft : Joystick; private var joystickRight : Joystick;
private var mainCameraTransform : Transform; private var cameraVelocity : Vector3 = Vector3.zero; private var cameraOffset : Vector3 = Vector3.zero; private var initOffsetToPlayer : Vector3;
// Prepare a cursor point varibale. This is the mouse position on PC and controlled by the thumbstick on mobiles. private var cursorScreenPosition : Vector3;
private var playerMovementPlane : Plane;
private var joystickRightGO : GameObject;
private var screenMovementSpace : Quaternion; private var screenMovementForward : Vector3; private var screenMovementRight : Vector3;
function Awake () {
motor.movementDirection = Vector2.zero; motor.facingDirection = Vector2.zero;
// Set main camera
mainCamera = Camera.main;
mainCameraTransform = mainCamera.transform;
// Ensure we have character set
// Default to using the transform this component is on
if (!character)
character = transform;
initOffsetToPlayer = mainCameraTransform.position - character.position;
#if UNITY_IPHONE || UNITY_ANDROID
if (joystickPrefab) {
// Create left joystick
var joystickLeftGO : GameObject = Instantiate (joystickPrefab) as GameObject;
joystickLeftGO.name = "Joystick Left";
joystickLeft = joystickLeftGO.GetComponent.<Joystick> ();
// Create right joystick
joystickRightGO = Instantiate (joystickPrefab) as GameObject;
joystickRightGO.name = "Joystick Right";
joystickRight = joystickRightGO.GetComponent.<Joystick> ();
}
#elif !UNITY_FLASH
if (cursorPrefab) {
cursorObject = (Instantiate (cursorPrefab) as GameObject).transform;
}
#endif
// Save camera offset so we can use it in the first frame
cameraOffset = mainCameraTransform.position - character.position;
// Set the initial cursor position to the center of the screen
cursorScreenPosition = Vector3 (0.5 * Screen.width, 0.5 * Screen.height, 0);
// caching movement plane
playerMovementPlane = new Plane (character.up, character.position + character.up * cursorPlaneHeight);
}
function Start () { #if UNITY_IPHONE || UNITY_ANDROID // Move to right side of screen var guiTex : GUITexture = joystickRightGO.GetComponent. (); guiTex.pixelInset.x = Screen.width - guiTex.pixelInset.x - guiTex.pixelInset.width; #endif
// it's fine to calculate this on Start () as the camera is static in rotation
screenMovementSpace = Quaternion.Euler (0, mainCameraTransform.eulerAngles.y, 0);
screenMovementForward = screenMovementSpace * Vector3.forward;
screenMovementRight = screenMovementSpace * Vector3.right;
}
function OnDisable () { if (joystickLeft) joystickLeft.enabled = false;
if (joystickRight)
joystickRight.enabled = false;
}
function OnEnable () { if (joystickLeft) joystickLeft.enabled = true;
if (joystickRight)
joystickRight.enabled = true;
}
function Update () { // HANDLE CHARACTER MOVEMENT DIRECTION #if UNITY_IPHONE || UNITY_ANDROID motor.movementDirection = joystickLeft.position.x screenMovementRight + joystickLeft.position.y screenMovementForward; #else motor.movementDirection = Input.GetAxis ("Horizontal") screenMovementRight + Input.GetAxis ("Vertical") screenMovementForward; #endif
// Make sure the direction vector doesn't exceed a length of 1
// so the character can't move faster diagonally than horizontally or vertically
if (motor.movementDirection.sqrMagnitude > 1)
motor.movementDirection.Normalize();
// HANDLE CHARACTER FACING DIRECTION AND SCREEN FOCUS POINT
// First update the camera position to take into account how much the character moved since last frame
//mainCameraTransform.position = Vector3.Lerp (mainCameraTransform.position, character.position + cameraOffset, Time.deltaTime * 45.0f * deathSmoothoutMultiplier);
// Set up the movement plane of the character, so screenpositions
// can be converted into world positions on this plane
//playerMovementPlane = new Plane (Vector3.up, character.position + character.up * cursorPlaneHeight);
// optimization (instead of newing Plane):
playerMovementPlane.normal = character.up;
playerMovementPlane.distance = -character.position.y + cursorPlaneHeight;
// used to adjust the camera based on cursor or joystick position
var cameraAdjustmentVector : Vector3 = Vector3.zero;
#if UNITY_IPHONE || UNITY_ANDROID
// On mobiles, use the thumb stick and convert it into screen movement space
motor.facingDirection = joystickRight.position.x * screenMovementRight + joystickRight.position.y * screenMovementForward;
cameraAdjustmentVector = motor.facingDirection;
#else
#if !UNITY_EDITOR && (UNITY_XBOX360 || UNITY_PS3)
// On consoles use the analog sticks
var axisX : float = Input.GetAxis("LookHorizontal");
var axisY : float = Input.GetAxis("LookVertical");
motor.facingDirection = axisX * screenMovementRight + axisY * screenMovementForward;
cameraAdjustmentVector = motor.facingDirection;
#else
// On PC, the cursor point is the mouse position
var cursorScreenPosition : Vector3 = Input.mousePosition;
// Find out where the mouse ray intersects with the movement plane of the player
var cursorWorldPosition : Vector3 = ScreenPointToWorldPointOnPlane (cursorScreenPosition, playerMovementPlane, mainCamera);
var halfWidth : float = Screen.width / 2.0f;
var halfHeight : float = Screen.height / 2.0f;
var maxHalf : float = Mathf.Max (halfWidth, halfHeight);
// Acquire the relative screen position
var posRel : Vector3 = cursorScreenPosition - Vector3 (halfWidth, halfHeight, cursorScreenPosition.z);
posRel.x /= maxHalf;
posRel.y /= maxHalf;
cameraAdjustmentVector = posRel.x * screenMovementRight + posRel.y * screenMovementForward;
cameraAdjustmentVector.y = 0.0;
// The facing direction is the direction from the character to the cursor world position
motor.facingDirection = (cursorWorldPosition - character.position);
motor.facingDirection.y = 0;
// Draw the cursor nicely
HandleCursorAlignment (cursorWorldPosition);
#endif
#endif
// HANDLE CAMERA POSITION
// Set the target position of the camera to point at the focus point
var cameraTargetPosition : Vector3 = character.position + initOffsetToPlayer + cameraAdjustmentVector * cameraPreview;
// Apply some smoothing to the camera movement
mainCameraTransform.position = Vector3.SmoothDamp (mainCameraTransform.position, cameraTargetPosition, cameraVelocity, cameraSmoothing);
// Save camera offset so we can use it in the next frame
cameraOffset = mainCameraTransform.position - character.position;
}
public static function PlaneRayIntersection (plane : Plane, ray : Ray) : Vector3 { var dist : float; plane.Raycast (ray, dist); return ray.GetPoint (dist); }
public static function ScreenPointToWorldPointOnPlane (screenPoint : Vector3, plane : Plane, camera : Camera) : Vector3 { // Set up a ray corresponding to the screen position var ray : Ray = camera.ScreenPointToRay (screenPoint);
// Find out where the ray intersects with the plane
return PlaneRayIntersection (plane, ray);
}
function HandleCursorAlignment (cursorWorldPosition : Vector3) { if (!cursorObject) return;
// HANDLE CURSOR POSITION
// Set the position of the cursor object
cursorObject.position = cursorWorldPosition;
#if !UNITY_FLASH
// Hide mouse cursor when within screen area, since we're showing game cursor instead
Screen.showCursor = (Input.mousePosition.x < 0 || Input.mousePosition.x > Screen.width || Input.mousePosition.y < 0 || Input.mousePosition.y > Screen.height);
#endif
// HANDLE CURSOR ROTATION
var cursorWorldRotation : Quaternion = cursorObject.rotation;
if (motor.facingDirection != Vector3.zero)
cursorWorldRotation = Quaternion.LookRotation (motor.facingDirection);
// Calculate cursor billboard rotation
var cursorScreenspaceDirection : Vector3 = Input.mousePosition - mainCamera.WorldToScreenPoint (transform.position + character.up * cursorPlaneHeight);
cursorScreenspaceDirection.z = 0;
var cursorBillboardRotation : Quaternion = mainCameraTransform.rotation * Quaternion.LookRotation (cursorScreenspaceDirection, -Vector3.forward);
// Set cursor rotation
cursorObject.rotation = Quaternion.Slerp (cursorWorldRotation, cursorBillboardRotation, cursorFacingCamera);
// HANDLE CURSOR SCALING
// The cursor is placed in the world so it gets smaller with perspective.
// Scale it by the inverse of the distance to the camera plane to compensate for that.
var compensatedScale : float = 0.1 * Vector3.Dot (cursorWorldPosition - mainCameraTransform.position, mainCameraTransform.forward);
// Make the cursor smaller when close to character
var cursorScaleMultiplier : float = Mathf.Lerp (0.7, 1.0, Mathf.InverseLerp (0.5, 4.0, motor.facingDirection.magnitude));
// Set the scale of the cursor
cursorObject.localScale = Vector3.one * Mathf.Lerp (compensatedScale, 1, cursorSmallerWithDistance) * cursorScaleMultiplier;
// DEBUG - REMOVE LATER
if (Input.GetKey(KeyCode.O)) cursorFacingCamera += Time.deltaTime * 0.5;
if (Input.GetKey(KeyCode.P)) cursorFacingCamera -= Time.deltaTime * 0.5;
cursorFacingCamera = Mathf.Clamp01(cursorFacingCamera);
if (Input.GetKey(KeyCode.K)) cursorSmallerWithDistance += Time.deltaTime * 0.5;
if (Input.GetKey(KeyCode.L)) cursorSmallerWithDistance -= Time.deltaTime * 0.5;
cursorSmallerWithDistance = Mathf.Clamp01(cursorSmallerWithDistance);
} ,Thanks, so how do would the script be phrased? I am not familiarized with how to script.
Answer by Tinus · Jan 11, 2013 at 03:00 PM
Appart from input handling and camera setup you also need multiple audio listeners, one for each player. Unity can't do this by default though.
I'm developing a Multi Audio Listener plugin based on Unity's default audio components.
The plugin is currently available for testing (on demand) and will later be sold on the Asset Store. Contact me if you're interested!
Answer by gkepets · Feb 22, 2015 at 04:20 PM
Having multiple keyboards can get complicated if you want the same controls for each one, but try setting up multiple different input combinations for 4 different players in the player input settings. The scripts will the stay the same but for each player it will expect different keys. (the fire1 key might be a w on one keyboard or the up arrow key on another)