Hello All,
I believed I’d create somewhat tutorial on making a primary particular person digital camera and controls. First particular person digital camera and controls will open up many door methods in making many various video games so having the ability to do that rapidly and easily is essential. So this tutorial goals to be that. One thing you need to use time and time once more and edit nevertheless you want. I’m not going to get into too many specifics.
So to start out create a brand new empty(3D) challenge. I’m at the moment utilizing Editor model 3.5.0, though hopefully every thing ought to work in newer variations too.
As soon as created add a brand new “Scene” within the Belongings panel:
I then add a brand new Folder and name it “Scripts” I then proper click on on the folder and create new TypeScript → NewComponent. I make three of those referred to as cameraScript, globalVars and playerScript.
I then create a brand new terrain within the property panel referred to as “Terrain”.
Okay now meaning our property are all arrange. Now we are able to make the modifications to the scene. I first drag the terrain over to the editor window. Then create a brand new Capsule.
I then identify the Capsule “Participant” and place it above the terrain.
I then drag the “playerScript” from the Belongings panel over to the item inspector. Then add two new physics parts referred to as RigidBody and SphereCollider. The rigidbody offers the character it’s physics. I’ve set mass to 70, Linear and Angular damping each to 0.2, Linear Issue (1,1,1) and Angular Issue to (0,0,0). The SphereCollider offers the item its physics form. I set the Radius to 2.
I then choose the Terrain object. I give it 2 physics parts. RigidBody and TerrainCollider. I set the Rigidbody sort to static as this terrain received’t be shifting wherever. The TerrainCollider makes use of the terrain mesh for the physics. I additionally needed to take away the terrain urgent the x subsequent to it and choosing the Terrain.terrain.
Last item we have to do is choose the Principal Digicam that ought to already be in your scene. Drag the “cameraScript” from the property panel over to the item inspector. I additionally modified the FOV to 60.
You possibly can then edit your terrain and make it look nevertheless you need.
So now for the script. I’ve stored it so simple as potential to comply with however to make issues simpler I’ll clarify that the globalVars is the place you may add extra international variables if you want. I put the digital camera node and participant node within the character and digital camera international variables. Which permits for these to be referred to as from wherever.
cameraScript
import { _decorator, Element, Enter, Vec3, enter, recreation, Node } from 'cc';
import { globalVars } from './globalVars';
const { ccclass, property } = _decorator;
@ccclass('cameraScript')
export class cameraScript extends Element {
/* Native Variables */
personal mouseXSensitvity: quantity = 8;
personal mouseYSensitvity: quantity = 5;
personal mousePos = new Vec3(0, 0, 0);
/* Finish Native Variables */
begin() {
globalVars.begin = 0;
globalVars.digital camera = this;
doc.addEventListener('pointerlockchange', this.lockChange, false);
enter.on(Enter.EventType.MOUSE_MOVE, this.onMouseMove, this);
enter.on(Enter.EventType.MOUSE_UP, this.onMouseUp, this);
}
replace(deltaTime: quantity) {
this.node.setPosition(globalVars.character.node.getPosition());
if(globalVars.begin == 1){
if(this.mousePos.x >= 300 && this.mousePos.x <= 500){
this.node.setRotationFromEuler(this.mousePos);
} else if(this.mousePos.x < 300){
this.node.setRotationFromEuler(300, this.mousePos.y,0);
} else if(this.mousePos.x > 500){
this.node.setRotationFromEuler(500, this.mousePos.y,0);
}
globalVars.character.node.setRotationFromEuler(new Vec3(0, this.mousePos.y, 0));
}
}
onMouseUp(occasion:EventMouse){
if(globalVars.begin == 0){
if (recreation.canvas.requestPointerLock) {
recreation.canvas.requestPointerLock();
}
}
}
lockChange() {
if (doc.pointerLockElement === recreation.canvas ) {
globalVars.begin = 1;
} else {
globalVars.begin = 3;
setTimeout( () => { globalVars.begin = 0; }, 1800 );
}
}
onMouseMove(occasion:EventMouse){
this.mousePos.x = 330 + occasion.getLocation().y/this.mouseXSensitvity;
this.mousePos.y = -event.getLocation().x/this.mouseYSensitvity;
}
}
globalVars
import { _decorator, Element } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('globalVars')
export class globalVars extends Element {
/* International Variables */
public character;
public digital camera;
public begin = 0;
/* Finish International Variables */
}
playerScript
import { _decorator, Element, Node, recreation, enter, Enter, KeyCode, EventKeyboard, Vec3, SphereCollider, ICollisionEvent, RigidBody } from 'cc';
import { globalVars } from './globalVars';
const { ccclass, property } = _decorator;
@ccclass('PlayerScript')
export class PlayerScript extends Element {
/* Native Variables */
personal movementSpeed = 3;
personal jumpStrength = 300;
personal crouch = 0;
personal moveForward = 0;
personal moveBackward = 0;
personal moveLeft = 0;
personal moveRight = 0;
personal setSpeed = 0.12;
personal maxSpeed = 0;
personal pace = 1;
personal grounded = false;
personal collider: SphereCollider = null!;
personal playerHeight = 2;
/* Finish Native Variables */
begin() {
globalVars.character = this;
enter.on(Enter.EventType.KEY_DOWN, this.onKeyDown, this);
enter.on(Enter.EventType.KEY_UP, this.onKeyUp, this)
this.node.getComponent(SphereCollider).on('onCollisionStay', this.OnCollisionStay, this);
this.node.getComponent(SphereCollider).on('onCollisionExit', this.OnCollisionExit, this);
this.node.getComponent(SphereCollider).radius = this.playerHeight;
this.maxSpeed = this.setSpeed;
}
OnCollisionStay(occasion: ICollisionEvent) {
occasion.contacts.forEach(contact => {
set free: Vec3 = new Vec3();
contact.getWorldNormalOnB(out);
if (Vec3.angle(out, Vec3.UP) < 60) {
this.grounded = true;
}
});
}
OnCollisionExit() {
this.grounded = false;
}
onKeyDown(occasion: EventKeyboard){
change(occasion.keyCode) {
case KeyCode.KEY_A: {
this.moveLeft = 1;
break;}
case KeyCode.KEY_W: {
this.moveForward = 1;
break;}
case KeyCode.KEY_D: {
this.moveRight = 1;
break;}
case KeyCode.KEY_S: {
this.moveBackward = 1;
break;}
case KeyCode.SHIFT_LEFT: {
this.pace = 1.1;
break;}
case KeyCode.KEY_C: {
if(this.crouch == 0){
this.crouch = 1;
this.node.getComponent(RigidBody).clearForces();
this.node.getComponent(SphereCollider).radius = this.playerHeight/1.4;
this.maxSpeed = this.setSpeed/1.4;
} else if(this.crouch == 1){
this.crouch = 0;
this.node.getComponent(SphereCollider).radius = this.playerHeight;
this.maxSpeed = this.setSpeed;
}
break;}
case KeyCode.SPACE: {
if(this.grounded && this.crouch == 0){
this.node.getComponent(RigidBody).applyLocalForce(new Vec3(0,this.jumpStrength*this.node.getComponent(RigidBody).mass,0), new Vec3(0,10,0));
}
break;}
}
}
onKeyUp(occasion: EventKeyboard){
change(occasion.keyCode) {
case KeyCode.KEY_A: {
this.moveLeft = 0;
break;}
case KeyCode.KEY_W: {
this.moveForward = 0;
break;}
case KeyCode.KEY_D: {
this.moveRight = 0;
break;}
case KeyCode.KEY_S: {
this.moveBackward = 0;
break;}
case KeyCode.SHIFT_LEFT: {
this.pace = 1;
break;}
}
}
replace(deltaTime: quantity) {
if(this.moveForward && this.moveLeft){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(-((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace,0,-((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace));
} else if(this.moveForward && this.moveRight){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace,0,-((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace));
} else if(this.moveBackward && this.moveLeft){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(-((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace,0,((this.maxSpeed/4)*this.node.getComponent(RigidBody).mass)*this.pace));
} else if(this.moveBackward && this.moveRight){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace,0,((this.maxSpeed/4)*this.node.getComponent(RigidBody).mass)*this.pace));
} else if(this.moveForward){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(0,0,-(this.maxSpeed*this.node.getComponent(RigidBody).mass)*this.pace));
} else if(this.moveBackward){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(0,0,((this.maxSpeed/2)*this.node.getComponent(RigidBody).mass)*this.pace));
} else if(this.moveLeft){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3(-(this.maxSpeed*this.node.getComponent(RigidBody).mass)*this.pace,0,0));
} else if(this.moveRight){
this.node.getComponent(RigidBody).applyLocalImpulse(new Vec3((this.maxSpeed*this.node.getComponent(RigidBody).mass)*this.pace,0,0));
}
}
}
When you exchange your scripts with the above. Save the scripts and save the scene within the editor. Then take a look at the challenge and it is best to now have first particular person controls with AWSD motion, crouch (c key), dash (Maintain left shift) and soar (spacebar). If you click on on the window the mouse will disappear. Press the escape key to see the mouse once more.
Any questions or additions and many others. Please let me know.
Thanks,
-iDev