Problem with sending and receiving multiple (4+) bytes through serial.

I'm a bit of a beginner and I have tried many of the solutions posted on other threads about this but none have worked so I've come to ask for help!

So I'm making a remote controlled robot car that communicates with the remote using HC-05 bluetooth modules. I have an x-y joystick, a pushbutton, and a potentiometer on the remote that sends four bytes of data to the car. Here's the code:

unsigned int xAxis, yAxis, button;
int buttonPin = 2;
int potPin = A4;
unsigned int potValue;

void setup() {
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(38400);
}
void loop() {
  xAxis = analogRead(A0)/4; 
  yAxis = analogRead(A1)/4;
  button = digitalRead(buttonPin);
  potValue = analogRead(potPin)/4;  

  
 byte buf[4] = {xAxis , yAxis , button, potValue};

  Serial.write(buf, sizeof(buf));

  delay(20);
}

On the receiving end, I'm trying to assign those four bytes to the proper variables. The xAxis and yAxis variables control the motion of the car, the pushbutton toggles the max speed of the motor between 'slow' and 'fast', and the potValue turns a servo. Here's the part of the code:

void loop() {

  while (Serial.available() >= 4) {

    for (int i; i < 4; i++) {
      buf[i] = Serial.read();
     
    }
    delay(5);
  }
  xAxis = buf[0] * 4;
  yAxis = 1023 - (buf[1] * 4);
  pos = map(buf[3], 0, 255, 8, 180);
  buttonState = buf[2];

 
  delay(15);

 
  Serial.println(pos);
  Serial.println(xAxis);
  Serial.println(yAxis);
  Serial.println(buttonState);
  Serial.println("");

}

My problem is that the variables seem to get assigned randomly and it changes every time I reset either of the boards. What am I doing wrong here? From my limited knowledge, I would expect the four bytes to be sent to the buffer sequentially and read in the proper order, but it's not doing that. Is there a better, more proper way to do this? Any help would be appreciated! Thanks

The serial input basics thread has information that will help you with reliable serial comms. Example #5 shows how to receive a comma delimited character string and parse the data, but it is best if you go through the tutorial step by step so that you understand the functions. To build the packet on the transmitting end, use successive serial prints or build the packet with sprintf().

  pinMode(A0, INPUT);
  pinMode(A1, INPUT);

These calls affect the digital nature of the pin. You are not using the pins as digital pins. So, you do not need to call pinMode() for these pins.

    for (int i; i < 4; i++) {
      buf[i] = Serial.read();
     
    }

On the first iteration of this loop, which element of the buf array are you writing to? If you said 0, you might be right. Or, you might be completely wrong. You have NO way of knowing what value a local variable will have UNLESS YOU GIVE IT ONE.

So, do NOT declare local variables without giving them initial values. EVER.

byte buf[4] = {xAxis , yAxis , button, potValue};

4 unsigned int variables won't fit into 4 bytes.

outsider:

byte buf[4] = {xAxis , yAxis , button, potValue};

4 unsigned int variables won't fit into 4 bytes.

The VALUES in those variables will.